板块一 Servlet编程:第三节 HttpServletRequest对象全解与请求转发 来自【汤米尼克的JAVAEE全套教程专栏】

本文主要是介绍板块一 Servlet编程:第三节 HttpServletRequest对象全解与请求转发 来自【汤米尼克的JAVAEE全套教程专栏】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

板块一 Servlet编程:第三节 HttpServletRequest对象全解与请求转发

  • 一、什么是HttpServletRequest
  • 二、接收请求的常用方法
  • 三、请求乱码问题
  • 四、请求转发:forward
  • 五、Request作用域
    • getParameter和getAttribute的区别

在上一节中我们已经学习了完整的Servlet的实现方式、Servle的工作流程和生命周期,但对于service(HttpServletRequest req, HttpServletResponse resp)中的两个重要形参还不了解,我们所有的请求响应都是通过这两个形参来实现的。这节教程开始将详解Servlet的几大对象。

一、什么是HttpServletRequest

HttpServletRequest对象:主要作用是用来接收客户端发送过来的请求信息。例如:请求的参数、发送的头信息等都属于客户端发来的信息,service()方法中形参接收的是HttpServletRequest接口的实例化对象,表示该对象主要应用在HTTP协议上,该对象是由Tomcat封装好传递过来。

  • HttpServletRequest是ServletRequest的子接口,ServletRequest只有一个子接口,就是HttpServletRequest。既然只有一个子接口为什么不将两个接口合并为一个?从长远上讲:现在主要用的协议是HTTP协议,但以后可能出现更多新的协议。若以后想要支持这种新协议,只需要直接继承ServletRequest接口就可以
  • 在HttpServletRequest接口中,定义的方法很多,但都是围绕接收客户端参数的。我们只需直接在service() 方法中由对象传入过来,数据自然就已经被封装在对象容器中了,这为我们所有请求的进行分析、处理提供了非常便捷的操作方式

二、接收请求的常用方法

在这里插入图片描述
实例
我们在helloServlet.java的service()方法中添上这些方法

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.service(req, resp);String userName = req.getParameter("");String url = req.getRequestURI();System.out.println("获取请求的完整路径:" + url);String queryString = req.getQueryString();//URL中?后面的参数部分System.out.println("获取请求的参数字符串:(?后面):" + queryString);String method = req.getMethod();System.out.println("获取请求方式:" + method);String protocol = req.getProtocol();System.out.println("获取当前协议版本:" + protocol);String  webapp = req.getContextPath();//      获取指定的参数System.out.println("获取项目站点名(对外访问路径):" + webapp);String name=req.getParameter("name");System.out.println("接受到的参数是:"+ name + '\n');}

启动服务器,浏览器访问项目,控制台输出
在这里插入图片描述
其中getParameter("...")是个很重要的方法,它可以根据参数名称获取参数值

//      获取指定的参数System.out.println("获取项目站点名(对外访问路径):" + webapp);String name=req.getParameter("name");System.out.println("接受到的参数是:"+ name + '\n');

实例
当上面的代码在浏览器URL后面输入跟上参数name=ToomyNike
在这里插入图片描述
控制台得
在这里插入图片描述

三、请求乱码问题

由于现在的request属于接收客户端的参数,所以必然有其默认的语言编码,不同版本的服务器,不同的请求方式都会产生不一样的效果

Tomcat 8及以上Tomcat 7及以下
GET请求不会乱码会乱码,使用new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");
POST请求会乱码,设置服务器编码格式request.setCharacterEncoding("UTF-8");会乱码,设置服务器编码格式request.setCharacterEncoding("UTF-8");

主要是由于在解析过程中默认使用的编码方式为ISO-8859-1此编码不支持中文,所以解析时一定会出现乱码。要想解决这种乱码问题,需要设置Request中的编码方式,告诉服务器以何种方式来解析数据。或者在接收到乱码数据以后,再通过相应的编码格式还原。

实例:当前是Tomcat8.5 以POST请求提交给helloServlet.java的Servlet进行测试
我们在web目录下新建hello.jsp文件
在这里插入图片描述

写入以POST为提交方式的测试表单,注意提交路径只需写为我们Servlet里@WebServlet("/helloServlet")注释的路径即可,之后遇到不再赘述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>hello</title><h1>Tomcat with IDEA</h1></head><body><form action="helloServlet" method="post">输入参数<input type="text" name="name"><button>提交</button></form></body>
</html>

启动服务器在浏览器中访问hello.jsp,输入中文参数,点击提交,跳转到helloServlet.java
在这里插入图片描述

控制台输出的内容是乱码
在这里插入图片描述
解决方式

  • 方式一 设置服务器编码格式request.setCharacterEncoding("UTF-8");这种方式只针对POST有效且必须在接收所有的数据之前设定

实例
在helloServlet.java的service()中,接受参数参数之前添上代码

        req.setCharacterEncoding("UTF-8");String name=req.getParameter("name");System.out.println("接受到的参数是:"+ name + '\n');

便解决中文乱码问题了
在这里插入图片描述

  • 方式二 在获取参数时使用String对象的方法new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");该种方式对任何请求有效,是通用的。注意Tomcat8起,以后的GET方式请求是不会出现乱码的,并且Tomcat8以上的GET请求强行使用此方法还会导致乱码

四、请求转发:forward

请求转发是一种服务器的行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的URL地址不会改变,得到响应后,服务器端再将响应发送给客户端,从始至终只有一个请求发出。

实现方式如下,达到多个资源协同响应的效果

request.getRequestDispatcher("url").forward(request, response);

实例
在helloServlet.java中写入测试代码

        //接收客户端请求的参数String name=req.getParameter("name");System.out.println("helloServlet接受到了参数:"+ name);// 请求转发跳转到req.getRequestDispatcher( "Servlet_do").forward(req,resp);

在Servlet_do.java中写入接受参数的代码

        String name=req.getParameter("name");System.out.println("Servlet_do接受到了参数:"+ name);

启动服务器,在浏览器中访问helloServlet并传递参数,提交后发现地址栏没有改变
在这里插入图片描述
控制台两个文件都打印了
在这里插入图片描述
说明参数在helloServlet中成功请求转发到了Servlet_do中
此时,如果直接访问Servlet_do
在这里插入图片描述
会发现控制台接收不到参数
在这里插入图片描述
这是因为请求转发从始至终只有一个请求,就是helloServlet的Request对象

五、Request作用域

在上面的代码中,我们通过浏览器的地址栏或者jsp的表单提交了很多参数,在Servlet中用Request对象的req.getParameter("name")方法接受了这些参数,除了这个方法,Request对象也可以在一个请求中传递数据,作用范围:在一次请求中有效,即服务器跳转有效,除了接受参数,它还可以设置内容或者删除内容

// 设置域对象内容 第一个参数为名称,第二个参数为内容
request.setAttribute(String name, Obj value);
// 获取域对象内容
request.getAttribute(String name);
// 删除域对象内容
request. removeAttribute(String name);

实例
新建一个start.java作为我们发送参数的Servlet

package www.caijiyuan;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/start")
public class start extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置参数age的内容req.setAttribute("age",18);// 请求转发跳转到after.javareq.getRequestDispatcher( "after").forward(req,resp);}
}

新建一个after.java作为我们接受参数的Servlet

package www.caijiyuan;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/after")
public class after extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int age = (int) req.getAttribute("age");System.out.println("接受到的参数为:" + age);}
}

启动服务器,在浏览器访问start以后,控制台输出
在这里插入图片描述
就实现了一次Request作用域的完整范围,也就是一次请求转发的范围:
从始至终只有一个请求发出,也就只有start.java里的Request发出

getParameter和getAttribute的区别

那么好像req.getParameter("...")req.getAttribute("...")都可以接受参数,让人傻傻分不清楚,它们的区别是什么?
getParameter的过程如下图
在这里插入图片描述
getAttribute过程如下图
在这里插入图片描述
二者可以具体区分为这个表格

getParametergetAttribute
获取的是客户端设置的数据获取的是服务器设置的数据
永远返回字符串返回值是任意类型

既然parameter和attribute都是传递参数,为什么不直接使用parameter呢?

  • 服务器端不能通过setParameter(key,value)来添加参数,因为没有这个函数,所以如果需要在服务器端进行跳转,并需要想下个页面发送新的参数时,则没法实现。是Attribute可以,可以通setAttribute()将值放入到request对象,然后在其他页面使用getAttribute获取对应的值,这样就达到一次请求可以在多个页面共享一些对象信息
  • parameter返回值是字符串,意味着不能传递其他的对象,如Map,List,但是attribute则可以存放任意类型的Java对象

以上就是HttpServletRequest对象的所有基础内容了,下一节我们将学习请求的兄弟:HttpServletResponse(响应)对象

这篇关于板块一 Servlet编程:第三节 HttpServletRequest对象全解与请求转发 来自【汤米尼克的JAVAEE全套教程专栏】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/728316

相关文章

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co