Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解(1)https://developer.aliyun.com/article/1518154
7.3 Request通用方式获取请求参数
Map<String,String[]>getParameterMap()
:获取所有参数Map集合String[]getParameterValues(String name)
:根据名称获取参数值(数组)String getParameter(String name)
:根据名称获取参数值(单个值)- get方式:
- html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>doPost</title> </head> <body> <form action="/BBS/demo5" method="get"> <input type="text" name="username"><br> <input type="password" name="password"><br> <input type="checkbox" name="hobby" value="1"> 游泳 <input type="checkbox" name="hobby" value="2"> 跑步 <br> <input type="submit"> </form> </body> </html>
- Java代码:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //Get请求 System.out.println("get..."); //1.获取所有参数的Map集合 Map<String, String[]> parameterMap = req.getParameterMap(); for (String key : parameterMap.keySet()) { System.out.print(key + ": "); //获取值 String[] strings = parameterMap.get(key); for (String string : strings) { System.out.print(string + " "); } System.out.println(); } System.out.println("----------------------"); //2.根据key获取值 String[] hobbies = req.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } System.out.println("----------------------"); //3.获取单个参数 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); }
- post方式:
- html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>doPost</title> </head> <body> <form action="/BBS/demo5" method="post"> <input type="text" name="username"><br> <input type="password" name="password"><br> <input type="checkbox" name="hobby" value="1"> 游泳 <input type="checkbox" name="hobby" value="2"> 跑步 <br> <input type="submit"> </form> </body> </html>
- Java代码:
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //Post请求 System.out.println("get..."); //1.获取所有参数的Map集合 Map<String, String[]> parameterMap = req.getParameterMap(); for (String key : parameterMap.keySet()) { System.out.print(key + ": "); //获取值 String[] strings = parameterMap.get(key); for (String string : strings) { System.out.print(string + " "); } System.out.println(); } System.out.println("----------------------"); //2.根据key获取值 String[] hobbies = req.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } System.out.println("----------------------"); //3.获取单个参数 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); }
- 通用代码:
@WebServlet("/demo5") public class ServletDemo5 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //Get请求 System.out.println("get..."); //1.获取所有参数的Map集合 Map<String, String[]> parameterMap = req.getParameterMap(); for (String key : parameterMap.keySet()) { System.out.print(key + ": "); //获取值 String[] strings = parameterMap.get(key); for (String string : strings) { System.out.print(string + " "); } System.out.println(); } System.out.println("----------------------"); //2.根据key获取值 String[] hobbies = req.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } System.out.println("----------------------"); //3.获取单个参数 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
7.4 请求参数中文乱码处理
7.4.1 POST 解决方案
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码POST //设置字符输入流的编码 req.setCharacterEncoding("utf-8"); //获取数据 String username = req.getParameter("username"); System.out.println(username); }
7.4.1 GET 解决方案
- GET获取参数方式:
getQueryString
- 产生乱码的原因:
- 浏览器在解析中文字符时采用UTF-8的字符集通过URL进行编码,将中文转换成
%
+16进制数
的格式,然后将转换后的字符发送给服务器进行解码,tomcat在进行解码时是通过ISO-8859-1
的字符集进行URL解码,由于编码和解码时用的字符集不同,所以就会出现乱码。
- URL编码:
- 将字符串按照编码方式转为二进制
- 每个字节转为2个16进制数并在前边加上%
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码GET String username = req.getParameter("username"); //转换为字节数据,编码 byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1); //将字节数组转换为字符串,解码 username = new String(bytes,"utf-8"); System.out.println(username); }
- Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
7.5 Request请求转发
- 请求转发(forward):一种在服务器内部的资源跳转方式
req.getRequestDispatcher("资源B路径").forward(req,resp);
- 请求转发资源间共享数据:使用Request对象
void setAttribute(String name,Object o)
:存储数据到request域中Object getAttribute(String name)
:根据key,获取值void removeAttribute(String name)
:根据key,删除该键值对
@WebServlet("/demo7") public class ServletDemo7 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo7..."); //存储数据 req.setAttribute("msg","hello"); //请求转发 req.getRequestDispatcher("/demo8").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
@WebServlet("/demo8") public class ServletDemo8 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo8..."); //获取数据 Object msg = req.getAttribute("msg"); System.out.println(msg); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
- 请求转发特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源
- 一次请求,可以在转发的资源间使用request共享数据
八、Response
8.1 设置相应数据功能
- 响应数据分为3部分:
- 响应行
- 设置响应状态码:
void setStatus(int sc)
- 响应头
- 设置响应键值对
void setHeader(String name,String value)
- 响应体
- 获取字符输出流
PrintWriter getWriter();
- 获取字节输出流
ServletOutputStream getOutputStream();
8.2 完成重定向
- 重定向(Redirect):一种资源跳转方式
@WebServlet("/resp1") public class ResponseDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("resp1..."); //重定向 //设置响应状态码302 //resp.setStatus(302); //设置响应头 //resp.setHeader("Location","/BBS/resp2"); //简化方式 resp.sendRedirect("/BBS/resp2"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
@WebServlet("/resp2") public class ResponseDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("resp2..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
- 重定向特点:
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源(服务器内部、外部均可)
- 两次请求,不能在多个资源使用request:共享数据
8.3资源路径问题
- 明确路径谁使用?
- 浏览器使用:需要加虚拟目录(项目访问路径)
- 服务端使用:不需要加虚拟目录
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("resp1..."); //简化方式 //动态获取虚拟目录 String contextPath = req.getContextPath(); resp.sendRedirect(contextPath + "/resp2"); }
8.4 Response响应字符数据
- 使用:
- 1.通过Response对象获取字符输出流
PrintWriter writer resp.getWriter();
- 2.写数据
writer.write("hello~");
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter writer = resp.getWriter(); resp.setHeader("content-type","text/html"); writer.write("<h1>hello~</h1>"); writer.write("<h1>你好~</h1>"); }
注意:
- 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭
- 中文数据乱码:原因通过Response获取的字符输出流默认编码:
ISO-8859-1
8.5 Response响应字节数据
- 使用:
- 通过Response对象获取字符输出流
ServletOutputStream outputStream resp.getOutputStream();
- 写数据
outputStream.write("字节数据");
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //读取文件 FileInputStream fis = new FileInputStream("d://head.jpg"); //获取response字节输出流 ServletOutputStream os = resp.getOutputStream(); //完成流的copy byte[] buff = new byte[1024]; int len = 0; while ((len = fis.read(buff)) != -1) { os.write(buff,0,len); } fis.close(); }
- IOUtils工具类使用:
- 导入坐标:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- 使用:
IOUtils.copy(fis,os);
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //读取文件 FileInputStream fis = new FileInputStream("d://head.jpg"); //获取response字节输出流 ServletOutputStream os = resp.getOutputStream(); //完成流的copy IOUtils.copy(fis,os); fis.close(); }