16. Servlet入门 - request介绍以及使用

网友投稿 730 2022-11-22

16. Servlet入门 - request介绍以及使用

16. Servlet入门 - request介绍以及使用

16. Servlet入门 - request介绍以及使用

request概述

什么是request

在Servlet API中,定义了一个HttpServletRequest接口,它继承自ServletRequest接口,专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求头和请求体三部分,因此,在HttpServletRequest接口中定义了获取请求行、请求头和请求消息体的相关方法.

Web服务器收到客户端的request 的基本作用,下面我们来使用一下。

获取客户机信息(操作请求行)

请求方式  请求路径(URI)  协议版本

GET /requestDemo/register.htm?username=zs&password=123456 HTTP/1.1

getMethod();获取请求方式getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)getContextPath();    获得当前应用工程名(部署的路径);getRequestURI();获得请求地址,不带主机名getRequestURL();获得请求地址,带主机名getServerPort();获得服务端的端口getQueryString();获的请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)

1. 创建一个演示Servlet程序,如下:

image-20201228164510317

@WebServlet("/requestDemo")public class RequestServletDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("访问 RequestServletDemo ...."); }}

启动 tomcat 测试服务如下:

image-20201228164610934

可以看到成功访问了,那么下面我们来逐个演示一下获取客户端信息的方法。

2. getMethod();获取请求方式

image-20201228165148365

//**getMethod()**;获取请求方式String method = request.getMethod();System.out.println("获取请求方式 method: " + method);

3. getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)

image-20201228165349054

// **getRemoteAddr()** ;获取客户机的IP地址(知道是谁请求的)String remoteAddr = request.getRemoteAddr();System.out.println("获取客户机的IP地址: " + remoteAddr);

4.getContextPath();    获得当前应用工程名(部署的路径);

image-20201230234000886

// **getContextPath()**; 获得当前应用工程名(部署的路径);String contextPath = request.getContextPath();System.out.println("获得当前应用工程名(部署的路径): " + contextPath);

5.getRequestURI();获得请求地址,不带主机名

image-20201230234255331

// **getRequestURI();获得请求地址,不带主机名**String requestURI = request.getRequestURI();System.out.println("获得请求地址,不带主机名: " + requestURI);

6.getRequestURL();获得请求地址,带主机名

image-20201230234438317

// **getRequestURL();获得请求地址,带主机名**StringBuffer requestURL = request.getRequestURL();System.out.println("获得请求地址,带主机名: " + requestURL);

7. getServerPort();获得服务端的端口

image-20201230234808764

// getServerPort();获得服务端的端口int serverPort = request.getServerPort();System.out.println("获得服务端的端口: " + serverPort);

8. getQueryString();获的请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)

image-20201230235128191

// getQueryString();获的请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)String queryString = request.getQueryString();System.out.println("获的请求参数: " + queryString);

获得请求头信息(操作请求头)

请求头: 浏览器告诉服务器自己的属性,配置的, 以key value存在, 可能一个key对应多个value

img

使用 getHeader(String name); 可以获取以下信息

User-Agent: 浏览器信息Referer:来自哪个网站(防盗链)

image-20201231085654381

//根据请求头的name获取value//目标:获取name为user-agent的请求头的信息// User-Agent: 浏览器信息String header = request.getHeader("user-agent");System.out.println("获取的请求头agent为:" + header);// Referer:来自哪个网站(防盗链)String referer = request.getHeader("referer");System.out.println("来自哪个网站(防盗链) Referer:" + referer);

小结

操作请求行(获得客户机信息)

getMethod();  获得请求方式getRemoteAddr(); 获得客户机的IP地址getContextPath(); 获得项目的部署的路径getRequestURI();  获得URI(不带 获得URL(带浏览器信息Referer:来自哪个网站(防盗链)getHeader(String name);

获取请求参数以及乱码处理(操作请求体)

上面我们已经理解了通过 request 获取客户端 以及 请求头 的信息,下面我们来看看如何获取请求参数,以及对应的中文乱码问题处理。

request 获得请求参数的方法

方法名

描述

String getParameter(String name)

获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack

String[] getParameterValues(String name)

获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码

Map<String,String[]> getParameterMap()

获得所有的请求参数。key为参数名,value为key对应的所有的值。

下面我们来用代码快速示例演示一下。

1.获取指定参数名对应的值  getParameter(String name)

1.1 首先我们创建一个 Servlet,如下:

image-20210107213514678

经过测试,我们已经知道了 Servlet 能够正常访问了。

1.2 使用 getParameter(String name) 来获取一个 username 的参数

image-20210107213833663

// 使用 getParameter(String name) 来获取一个 username 的参数String username = request.getParameter("username");System.out.println("获取到的username参数: " + username);

那么这里带来一个疑问,如果是 post 请求呢?是否也可以获取参数呢?下面我们可以使用 postman 使用 form 表单的方式,快速测试一下,如下:

image-20210107214127912

我们使用 post 请求的方式,可以看到 Servlet 打印信息如下:

image-20210107214226773

2. 获得指定参数名对应的所有的值 getParameterValues(String name)。

获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码

2.1 测试使用 GET 的 query 请求方式

image-20210107220002203

// 获得指定参数名对应的所有的值 getParameterValues(String name)。String[] hobbies = request.getParameterValues("hobby");for (String hobby : hobbies) { System.out.println("获取的hobby:" + hobby);}

访问:hobby 参数。

2.2 测试用 POST 的 请求方式

image-20210107220150452

获取到参数如下:

image-20210107220249999

可以看到两种请求方式都可以获取参数。

3.获得所有的请求参数 getParameterMap()。key为参数名,value为key对应的所有的值。

image-20210107221251645

// 获得所有的请求参数 getParameterMap()System.out.println("获得所有的请求参数 getParameterMap(): ");Map parameterMap = request.getParameterMap();// 遍历所有参数 mapfor (Map.Entry entry : parameterMap.entrySet()) { // 遍历参数的value for (String value : entry.getValue()) { System.out.println(entry.getKey() + ": " + value); }}

中文乱码问题处理

上面我们设置请求参数的时候,都是采用英文,并没有使用中文内容,那么如果使用中文的话,会出现什么结果呢?

1.中文乱码问题

1.1 在 GET 请求参数中,设置中文内容

image-20210107222052303

访问 在 POST 请求参数中,设置中文内容

image-20210107222405433

image-20210107222442030

可以看到当我们使用 POST 请求参数为中文的时候,服务端接收的内容为乱码,这是为什么么?

2.中文乱码的产生原因(客户端与服务端两者的编码格式不一致)

我们在输入一些中文数据提交给服务器的时候,服务器解析显示出来的一堆无意义的字符,就是乱码。那么这个乱码是如何出现的呢?如下图所示:

image-20191209100446323

基本的原因其实就是 客户端 与 服务端 两者的编码格式不一致,那么我们只要将两边都设置为 ​​utf-8​​ 编码格式即可。

而在上面的示例中,我们发现GET请求中文乱码不用处理,而 POST 请求需要处理,总结如下:

get方式, 当 tomcat>=8.0, 乱码会由 tomcat 自动处理;而如果低于 8.0 ,也是需要自己设置一下编码格式。post方式, 目前的版本都需要自己设置编码格式。

所以,还是都自己设置一下编码格式就好了。

3.中文乱码的解决(设置服务端的解码格式为 utf-8)

image-20210107223051821

// 设置服务端为 utf-8 解码格式,解决中文乱码问题request.setCharacterEncoding("UTF-8");

4.设置编码格式的快速输入模板

在 IDEA 中,如果每次都要去记住如何输入,也是一个比较麻烦的事情,那么我们可以设置一个快捷输入方式,如下:

image-20210107233153227

request.setCharacterEncoding("UTF-8");

image-20210107233232778

测试输入如下:

image-20210107233257945

获取请求参数使用 BeanUtils 封装好 POJO 对象中

现在我们已经可以使用request对象来获取请求参数,但是,如果参数过多,我们就需要将数据封装到对象。

以前封装数据的时候,实体类有多少个字段,我们就需要手动编码调用多少次setXXX方法,因此,我们需要BeanUtils来解决这个问题。

BeanUtils是Apache Commons组件的成员之一,主要用于简化javaBean封装数据的操作。

使用步骤:

导入jar使用BeanUtils.populate(user,map)

1.使用 Maven 导入 BeanUtils 的 jar 包依赖

1.1 访问 Maven 仓库,搜索 BeanUtils 的依赖

访问 搜索 BeanUtils 如下:

image-20210107225030048

image-20210107225128037

image-20210107225235531

commons-beanutils commons-beanutils 1.9.3

1.2  在项目的 pom.xml 导入 BeanUtils 坐标依赖

image-20210107225418529

2.创建 POJO 包的 User 类

image-20210107225758825

package com.pojo;import java.util.Arrays;/** * @author Aron.li * @date 2021/1/7 22:56 */public class User { private String username; private String password; private String gender; private String[] hobby; public User() { } public User(String username, String password, String gender, String[] hobby) { this.username = username; this.password = password; this.gender = gender; this.hobby = hobby; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", gender='" + gender + '\'' + ", hobby=" + Arrays.toString(hobby) + '}'; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String[] getHobby() { return hobby; } public void setHobby(String[] hobby) { this.hobby = hobby; }}

3.使用 BeanUtils 将 与 User 类属性同名的 请求参数 进行自动批量赋值

image-20210107230727283

@WebServlet("/BeanUtilsDemo")public class BeanUtilsDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置请求参数的编码格式,解决中文乱码问题 request.setCharacterEncoding("UTF-8"); //1. 获取所有的请求参数 Map parameterMap = request.getParameterMap(); //2. 将请求参数封装到User对象中 User user = new User(); //3. 使用BeanUtils框架自动将map中的数据封装到对象中 try { BeanUtils.populate(user, parameterMap); } catch (Exception e) { e.printStackTrace(); } // 4. 打印封装好的user对象 System.out.println(user); }}

4.使用 post 请求 Servlet,每个请求参数都与 User 类中的属性同名

image-20210107230847532

请求之后,Servlet 程序打印封装好的 user 对象如下:

image-20210107230927807

那么如果缺少 或者 请求的参数 与 User 类属性不同名称 呢?

image-20210107231023378

image-20210107231040429

可以发现,如果请求的参数不同命,那么 BeanUtils 就无法对应赋值了。

request 的请求转发

在上面我们基本清楚了 request 如何获取请求头、请求参数等功能了,那么下面继续介绍 request 的请求转发功能。

1. 请求转发的格式

request.getRequestDispatcher(url).forward(request, response);//转发

2.请求转发的作用

当我们需要将 request 对象同时交给两个或者多个 Servlet 程序处理的时候,那么就可以使用请求转发。

request 请求转发不会修改浏览器的路径,也不需要浏览器跳转至其他路径,由服务端执行跳转。

更加重要的是,request 请求转发还可以访问 WEB-INF 中受保护的资源。

3.设置 请求转发的 forward 快捷输入模板

我们可以看到输入一个请求转发要写好多内容,为了方便,我们可以自己设置一下快捷方式,如下:

File | Settings | Editor | Live Templates

image-20210107232036814

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

image-20210107232718248

image-20210107232752324

下面在代码输入 ​​forward​​ 尝试快捷输入,如下:

image-20210107232829032

image-20210107232846420

4.请求转发的效果是跳转: 跳转到其它页面,跳转到其它的servlet

4.1 首先创建一个 Servlet 程序 forwardDemo1

image-20210108075753836

@WebServlet("/ForwardDemo1")public class ForwardDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("this is ForwardDemo1...."); }}

4.2 再创建一个 Servlet 程序 forwardDemo2

image-20210108075933510

@WebServlet("/ForwardDemo2")public class ForwardDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("this is ForwardDemo2...."); }}

4.3 在 forwardDemo1 中设置请求转发至 forwardDemo2

image-20210108080421057

@WebServlet("/ForwardDemo1")public class ForwardDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("this is ForwardDemo1...."); System.out.println("访问到 ForwardDemo1..."); // 请求转发至 forwardDemo2 request.getRequestDispatcher("/ForwardDemo2").forward(request, response); }}

我们从执行的效果来看,请求的确到了 demo1 的 Servlet 程序中,并且浏览器又直接显示 demo2 返回的结果,没有进行二次请求。

5.请求转发的跳转,只能是跳转到本项目的资源,无法访问项目外的资源

5.1 创建一个项目的 index.html ,用于演示请求转发

image-20210108080827164

5.2 在forwardDemo2中,再次设置请求转发至 index.html

image-20210108081024136

// 请求转发项目中的 index.htmlrequest.getRequestDispatcher("/index.html").forward(request, response);

5.3 接着上面的示例,首先请求 demo1,然后demo1 转发至 demo2,然后 demo2 转发至 index.html

image-20210108081159370

5.4 测试能否访问项目外的资源,例如:百度

image-20210108081337556

// 测试访问项目外的资源request.getRequestDispatcher("response);

可以看到请求失败了,无法请求转发无法访问项目外的资源。

6. 请求转发到WEB-INF中的资源

6.1 将上面写的 index.html 移动到 WEB-INF 中

image-20210108081547303

一般来说,WEB-INF的资源是受保护的,在浏览器无法访问。但是使用请求转发的话,就可以访问到了。

6.2 使用请求转发,访问 WEB-INF 中的 index.html

image-20210108081813515

// 请求转发至 WEB-INF 中的 index.htmlrequest.getRequestDispatcher("/WEB-INF/index.html").forward(request, response);

request 作为域对象存取值

在上面我们已经理解了 request 请求转发的功能,而伴随着 请求转发的 当然就是可以携带 request 对象的存储值了。

当然 Servlet 的域对象有四种,而 request 只是其中的一种。

ServletContext: 范围 整个应用(无论多少次请求,只要是这个应用里面的都是可以共享的)

request范围: 一次请求有效  (所以要结合请求转发使用)

域对象是一个容器,这种容器主要用于Servlet与Servlet/JSP之间的数据传输使用的。

Object getAttribute(String name) ;void setAttribute(String name,Object object)  ;void removeAttribute(String name)  ;

下面编写两个Servlet,进行 request 传值看看。

1.接着在上面的 forwardDemo1 中存储一个 name 值在 request 域对象中

image-20210108084315439

@WebServlet("/ForwardDemo1")public class ForwardDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("this is ForwardDemo1...."); System.out.println("访问到 ForwardDemo1..."); // 目标: 在ForwardDemo2中获取ForwardDemo1中的变量username的值 // 要求只能是由ForwardDemo1跳转到ForwardDemo2的时候才能获取 String username = "周杰棍"; //将username存储到request域对象中 request.setAttribute("name",username); // 请求转发至 forwardDemo2 request.getRequestDispatcher("/ForwardDemo2").forward(request, response); }}

2.在 forwardDemo2 中取 request 的 name 值

image-20210108084406991

@WebServlet("/ForwardDemo2")public class ForwardDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("this is ForwardDemo2...."); System.out.println("访问到 ForwardDemo2...."); // 获取request中的值 Object name = request.getAttribute("name"); System.out.println("从 ForwardDemo1 传递过来的 name: " + name); }}

3.测试请求

image-20210108084500341

可以看到,通过上面的示例,成功将 demo1 存储的值 转发到 demo2 上了。

4.小结

request 作为域对象存取数据

Object getAttribute(String name) ;  取void setAttribute(String name,Object object)  ; 存void removeAttribute(String name)  ; 移除

范围: 一次请求有效(转发可以使用)

image-20191209110018952

Request部分的小结

获取请求行的信息

获取请求方式:getMethod()获取请求的客户端的ip地址:getRemoteAddr()获取项目部署的路径:getContextPath()获取uri:统一资源标识符获取url:统一资源定位符获取服务器的端口号获取请求参数的字符串:getQueryString()

获取请求头的信息:getHeader(name)获取请求参数

getParameter(name)getParameterValues(name)getParameterMap()

使用BeanUtils将map中的数据存储到JavaBean对象中

map的key要和JavaBean的属性名保持一致,如果不一致那么该字段的值就无法存储BeanUtils中默认内置一些基本类型的转换器(如果map中的数据是string类型,JavaBean的属性还是int类型那么会自动转换)

使用request做请求转发: request.getRequestDispatcher("跳转路径").forward(request,response);request对象作为域对象向存取数据,它的作用范围是一次请求中,和请求转发一起使用

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:14. Servlet入门 - ServletContext类作为全局域对象共享数据使用
下一篇:CSS 定位布局 - 相对、绝对、固定三种定位
相关文章

 发表评论

暂时没有评论,来抢沙发吧~