洞察探索如何利用兼容微信生态的小程序容器,实现跨平台开发,助力金融和车联网行业的数字化转型。
794
2022-11-22
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
中文乱码问题处理
上面我们设置请求参数的时候,都是采用英文,并没有使用中文内容,那么如果使用中文的话,会出现什么结果呢?
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
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
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~