day16-Servlet05
Servlet05
14.HttpServletRequest
- HttpServletRequest对象代表客户端的请求
- 当 客户端/浏览器 通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中
- 通过这个对象的方法,可以获取客户端的信息
- HttpServletRequest类图

14.1HttpServletRequest常用方法
-
getRequestURI():获取请求的资源路径
http://localhost:8080
/servlet/loginServlet
-
getRequestURL():获取请求的统一资源定位符(绝对路径)
http://localhost:8080/servlet/loginServlet
-
getRemoteHost():获取客户端的主机
-
getRemoteAddr():获取客户端的ip
-
getHeader():获取请求头
-
getParameter():获取请求的参数
-
getParameterValues():获取请求的参数(多个值的时候使用)
-
getMethod():获取请求的方式get或post
-
setAttribute(key,value):设置域数据
-
getAttribute(key):获取域数据
-
getRequestDispatcher():获取请求转发对象(请求转发的核心对象)
14.2HttpServletRequest应用实例
需求:在一个表单提交数据给Servlet,在该Servlet中通过HttpServletRequest对象获取相关数据
package com.li.servlet.request; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet(name = "HttpServletRequestMethods", value = "/requestMethods") public class HttpServletRequestMethods extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //这里我们使用request对象,获取表单提交的各种数据 //System.out.println("HttpServletRequestMethods doPost()被调用..."); //1.获取和http请求头相关的信息 System.out.println("请求的资源URI= " + request.getRequestURI()); System.out.println("请求的统一资源定位符(绝对路径)URL= " + request.getRequestURL()); System.out.println("请求的客户端ip地址= " + request.getRemoteAddr()); /* getRemoteAddr()应用:发现某个ip在10s内访问的次数超过100次,就封ip 实现思路:1用一个集合concurrentHashMap[k=ip v=访问次数] 2启动线程定时扫描 3做出相应处理 */ //如果我们希望得到请求的头的相关信息,可以直接使用request.getHeader("请求头字段名") System.out.println("http请求头HOST= " + request.getHeader("Host")); System.out.println("该请求发起的地址是= " + request.getHeader("Referer")); //请获取访问网站的浏览器是什么? String userAgent = request.getHeader("User-Agent"); //User-Agent= Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0 String[] s = userAgent.split(" ");//使用空格分割 //取最后一个字符,再用 /分割,取第一个字符 System.out.println("浏览器的种类= " + s[s.length - 1].split("\\/")[0]); System.out.println("http请求方式= " + request.getMethod()); //2.获取和请求参数相关的信息,要去在返回数据前获取参数 //username=&pwd=&hobby=lb&hobby=cc //2.1获取表单的数据[单个数据] request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String pwd = request.getParameter("pwd"); //2.2获取表单一组数据[多个数据] String[] hobbies = request.getParameterValues("hobby"); System.out.println("username= " + username); System.out.println("pwd= " + pwd); //增强for循环的快捷键 iter->回车即可 for (String hobby : hobbies) { System.out.println("hobby= " + hobby); } //推而广之,如果是单选,下拉框等,获取数据的方法大同小异 } }
html页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册</title> </head> <body> <h1>注册用户</h1> <!--注意:这里的requestMethods不是你的类名,是你在web.xml里面(或者注解里面)配置的<url-pattern>--> <form action="http://localhost:8080/servlet_demo/requestMethods" method="post"> u:<input type="text" name="username"/><br/><br/> p:<input type="password" name="pwd"/><br/><br/> 选择你最喜欢的三国人物: <input type="checkbox" name="hobby" value="lb">刘备 <input type="checkbox" name="hobby" value="cc">曹操 <input type="checkbox" name="hobby" value="sq">孙权<br/><br/> <input type="submit" value="注册用户"> </form> </body> </html>
浏览器中访问html页面,输入数据,点击注册:

后台输出如下:

14.3HttpServletRequest注意事项和细节
-
获取doPost参数中文乱码解决方法,设置编码类型
request.setCharacterEncoding("UTF-8");
注意要写在获取参数之前:
-
注意:如果通过PrintWriter writer,有返回数据给浏览器,建议将获取参数的代码写在writer.print()之前,否则可能获取不到参数值(post)
-
处理http响应数中文乱码问题
-
再次理解HTTP协议响应Content-Type的含义,比如text/html,text/plain,application/x-tar
Content-Type表示返回的数据类型,浏览器会根据这个类型来解析数据,详见HTTP协议MIME类型
14.4请求转发
14.4.1为什么需要请求转发
-
目前我们学习的都是一次请求,对应一个Servlet
-
在实际的开发中,往往业务比较复杂,需要在一次请求中,使用到多个Servlet完成一个任务(Servlet链,流水作业)
14.4.2请求转发说明
-
实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理
-
HttpServletRequest对象(也叫request对象)提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发
-
request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他web资源处理
- setAttribute方法
- getAttribute方法
- removeAttribute方法
- getAttributeNames方法
14.4.3请求转发应用实例

例子
需求:浏览器在某html页面输入数据,checkServlet根据该数据对进行操作,如果输入的数据为“tom”,就将其设置为“管理员”,如果不是,就设置为“普通用户”,由managerServlet向服务器返回数据

CheckServlet:
package com.li.servlet.request; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet(urlPatterns = {"/checkServlet"}) public class CheckServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("CheckServlet doPost()被调用..."); //根据用户名来确定该用户是什么身份 String username = request.getParameter("username"); //注意:如果是同一个request对象(请求转发),那么可以在不同的Servlet中使用getParameter取出该参数 if ("tom".equals(username)) { //分配权限 //request对象是一个域对象,通过request对象,在实现转发时, // 把数据通过request对象带给其他web资源处理 request.setAttribute("role", "管理员");//k-v } else { request.setAttribute("role", "普通用户");//k-v } //获取分发器 /** * 1. /managerServlet写的是想转发的Servlet的url-pattern * 2. / 会被解析成 /servlet_demo * 因此请求转发是不可能转发到外网去的 * 3.forward(request,response)表示把当前的request和response对象传递给下一个Servlet使用, * 保证了下一个Servlet和当前的Servlet使用的是同一个request和response对象 */ RequestDispatcher requestDispatcher = request.getRequestDispatcher("/managerServlet"); requestDispatcher.forward(request, response); } }
ManagerServlet:
package com.li.servlet.request; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet(urlPatterns = {"/managerServlet"}) public class ManagerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("ManagerServlet doPost()被调用..."); //因为是同一个request对象,因此可以用request.getParameter("username")获取username String username = request.getParameter("username"); String role = (String) request.getAttribute("role");//k-v //输出信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("用户名:" + username + "<br/>"); writer.print("role:" + role); writer.flush(); writer.close(); } }
login.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <form action="http://localhost:8080/servlet_demo/checkServlet" method="post"> u:<input type="text" name="username"><br/> <input type="submit" value="登录"> </form> </body> </html>
redeployTomcat,在浏览器中访问http://localhost:8080/servlet_demo/login.html
,输入数据,点击登录,可以看到地址栏变为http://localhost:8080/servlet_demo/checkServlet
,但没有变为managerServlet(地址会保留在第一个Servlet的URL)
14.4.4请求转发注意细节
-
浏览器地址不会变化(地址会保留在第一个Servlet的URL)
-
在同一次HTTP请求中,进行多次转发,仍然是一次HTTP请求
-
在同一次HTTP请求中,进行多次转发,多个Servlet可以共享request域/对象的数据,即request域/对象的数据(参数,属性)的作用域,是在一次HTTP请求有效
因为是同一个request对象(数据上来讲)
-
可以转发到WEB-INF目录下
-
不能访问当前WEB工程外的资源
-
因为浏览器地址栏会停留在第一个Servlet,如果你刷新页面,会再次发出请求(并且会带数据)。
所以在支付页面情况下,不要使用请求转发,否则会造成重复支付 [解决方案可以使用重定向]

14.5习题
14.5.1习题一
通过HttpServletRequest对象获取到访问服务的的浏览器名称
通过字符串分割,14.2已完成
14.5.2习题二
请想办法获取到 JSESSIONID的值
//获取 JSESSIONID的值 String cookie = request.getHeader("Cookie"); String[] s1 = cookie.split(";"); String[] strings = s1[0].split("="); System.out.println("JSESSIONID的值= "+strings[1]);

14.5.3习题三
下面是一个表单,完成如下功能
(1)编写一个RegisterServlet,能够接收到提交的各种数据,并获取浏览器所在电脑的操作系统和位数
(2)并把接收到的数据返回给浏览器显示
(3)注意处理中文乱码问题
(4)暂不处理文件提交

RegisterServlet:
package com.li.servlet.request.homework; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; @WebServlet(urlPatterns = {"/registerServlet"}) public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取表单提交的数据 //先设置编码类型 request.setCharacterEncoding("utf-8"); //单个数据使用 getParameter String username = request.getParameter("username"); String pwd = request.getParameter("pwd"); String pwd2 = request.getParameter("pwd2"); //多个数据使用getParameterValues String[] sports = request.getParameterValues("sport"); String gender = request.getParameter("gender"); String city = request.getParameter("city"); String introduce = request.getParameter("introduce"); //2.获取用户浏览器所在电脑的操作系统和位数 //2.1法一-字符串分割 //Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0 String User_Agent = request.getHeader("User-Agent"); //String[] s = User_Agent.split(" ");//使用空格分割 //s[1]="(Windows" 取出索引为1及之后的字符串 //String OS = s[1].substring(1); //s[5]=x64; //String OSNum = s[5].substring(1, 3); //2.2法二-正则表达式 String regStr = "\\((.*)\\)"; Pattern compile = Pattern.compile(regStr); Matcher matcher = compile.matcher(User_Agent); matcher.find();//因为只有一组,所以没有必要使用循环 //String group = matcher.group(0);//(Windows NT 10.0; Win64; x64; rv:106.0) String group1 = matcher.group(1);//Windows NT 10.0; Win64; x64; rv:106.0 String[] split = group1.split(";"); //System.out.println(split[0]);//Windows NT 10.0 //System.out.println(split[1]);// Win64 //3.返回输出 //设置编码类型 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("你的用户名称:" + username + "<br/>"); writer.print("你的用户密码:" + pwd + "<br/>"); writer.print("你的确认密码:" + pwd2 + "<br/>"); writer.print("喜欢的运动:"); for (String sport : sports) { writer.print(sport + " "); } writer.print("<br/>你的性别:" + gender + "<br/>"); writer.print("喜欢的城市:" + city + "<br/>"); writer.print("自我介绍:" + introduce + "<br/>"); writer.print("电脑操作系统:" + split[0] + "<br/>"); writer.print("位数:" + split[1].trim() + "<br/>");//trim()去掉字符串左右两边的空格 writer.flush(); writer.close(); } }
register_form.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册</title> </head> <body> <form action="http://localhost:8080/servlet_demo/registerServlet" method="post"> 用户注册信息<br/> 用户名称:<input type="text" name="username"/><br/> 用户密码:<input type="password" name="pwd"/><br/> 确认密码:<input type="password" name="pwd2"/><br/> 请选中你喜欢的运动项目<br/> <input type="checkbox" name="sport" value="lq">篮球<br/> <input type="checkbox" name="sport" value="zq">足球<br/> <input type="checkbox" name="sport" value="sq">手球<br/> 请选中你的性别<br/> <input type="radio" name="gender" value="men">男<br/> <input type="radio" name="gender" value="women">女<br/> 请选中你喜欢的城市 <select name="city"> <option>--请选中--</option> <option value="gz">广州</option> <option value="bj">北京</option> <option value="sh">上海</option> </select><br/> 自我介绍<textarea name="introduce"></textarea><br/> <input type="submit" value="提交"> <input type="reset" value="重置"> </form> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!