概述

Interface ServletRequest

为什么要求是interface呢?

JavaEE规范。不同的服务器制作厂商全部必须要实现该接口,其实就是对于请求报文的封装。

ServletRequest—————-XXXXRequest、 YYYYYRequest

HttpServletRequest———ServletRequest 父子接口。

请求的话,协议其实有很多种,比如HTTP协议、AJP协议、HTTPS协议

共性的部分就是ServletRequest,个性的部分就是,比如HTTP协议,那么就是HttpServletRequest

当我们使用浏览器来访问时,你可以认为ServletRequest======等价于HttpServletRequest

常用方法

既然代表了请求报文的封装,那么完全可以利用里面的方法将请求报文重现

请求行:请求方法、请求资源、版本协议

请求头

请求体

  1. package com.cskaoyan.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Enumeration;
  9. @WebServlet("/request1")
  10. public class RequestServlet1 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. }
  13. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  14. //
  15. String method = request.getMethod();
  16. String requestURI = request.getRequestURI();
  17. String requestURL = request.getRequestURL().toString();
  18. String protocol = request.getProtocol();
  19. // 和list、set非常的相似 iterator
  20. Enumeration<String> headerNames = request.getHeaderNames();
  21. System.out.println(method + " " + requestURI + " " + protocol);
  22. while (headerNames.hasMoreElements()){
  23. String headerName = headerNames.nextElement();
  24. String headerValue = request.getHeader(headerName);
  25. System.out.println(headerName + " : " + headerValue);
  26. }
  27. }
  28. }
  1. package com.cskaoyan.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Enumeration;
  9. @WebServlet("/request2")
  10. public class RequestServlet2 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. }
  13. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  14. //除此之外,request中还包含有其他的一些有用的信息
  15. //可以获取客户机和服务器主机的信息
  16. String remoteAddr = request.getRemoteAddr();
  17. int remotePort = request.getRemotePort();
  18. String localAddr = request.getLocalAddr();
  19. int localPort = request.getLocalPort();
  20. System.out.println("客户机" + remoteAddr + " 端口号为:" + remotePort + "访问了当前服务器" + localAddr + "在" + localPort + "端口号监听的程序") ;
  21. }
  22. }

获取请求参数(4个API)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="http://localhost/app/form" method="post">
  9. <input type="text" name="username"><br>
  10. <input type="password" name="password"><br>
  11. <input type="radio" name="gender" value="male">
  12. <input type="radio" name="gender" value="female"><br>
  13. <input type="checkbox" name="hobby" value="sleep">睡觉
  14. <input type="checkbox" name="hobby" value="coding">码代码
  15. <input type="checkbox" name="hobby" value="honor">王者荣耀<br>
  16. <input type="submit">
  17. </form>
  18. </body>
  19. </html>
  1. package com.cskaoyan.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Arrays;
  9. @WebServlet("/form")
  10. public class FormServlet extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. //接收请求参数
  13. String username = request.getParameter("username");
  14. String password = request.getParameter("password");
  15. String gender = request.getParameter("gender");
  16. String[] hobbies = request.getParameterValues("hobby");
  17. System.out.println(username);
  18. System.out.println(password);
  19. System.out.println(gender);
  20. System.out.println(Arrays.toString(hobbies));
  21. }
  22. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  23. }
  24. }

优化

前端页面提交的参数非常多,如何能够让服务器这边处理的代码尽可能少一些,或者尽可能智能一些。

  1. package com.cskaoyan.request;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Arrays;
  9. import java.util.Enumeration;
  10. @WebServlet("/form2")
  11. public class FormServlet2 extends HttpServlet {
  12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13. //接收请求参数
  14. Enumeration<String> parameterNames = request.getParameterNames();
  15. while (parameterNames.hasMoreElements()){
  16. String key = parameterNames.nextElement();
  17. String[] values = request.getParameterValues(key);
  18. if(values.length == 1){
  19. System.out.println(key + ":" + values[0]);
  20. }else {
  21. System.out.println(key + ":" + Arrays.toString(values));
  22. }
  23. }
  24. }
  25. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  26. }
  27. }

封装数据到JavaBean

JavaBean代表什么意思?对象的封装。就是对象。但是和之前学习的一些对象略有一些不同

1.必须要有一个无参的构造函数(如果设置了一个有参的构造函数,那么一定要给它留一个无参的构造函数,否则很多情况下无法实例化对象出来)

2.成员变量一般设置为private,并且提供public的get和set方法

BeanUtils执行的时候,报错。

image.png

该报错信息,只有一个原因,在部署根目录下面WEB-INF/lib目录里面没有对应的jar包

运行时需要该jar包,但是呢,在lib目录里面没有对应的jar包,所以会报错。

解决方案:

image.png

思考一下,为什么servlet不需要?因为tomcat它的依赖中包含servlet。所以我们运行servlet不需要再额外的导包,其实使用的时tomcat的servlet包。类加载—-双亲委派机制。在加载一个类的时候,首先该类加载不会自己先去找,而是先把这个任务交给父加载器去找

请求参数中文乱码

使用post方式提交数据时,发现了中文乱码问题,乱码的原因?

编解码不一致。

请求报文发送过来的时候是什么编码格式。

根据html meta charset=utf-8可以确定前端提交过来的数据编码格式为utf-8,那么服务器接收到之后乱码了,服务器使用的不是utf-8

服务器默认使用的是ISO-8859-1,不支持中文的。

如何让服务器使用指定编码格式。

以post请求方式提交请求参数时,请求参数是在请求体里面的(浏览器的行为)postman

get请求方法和post的区别和请求参数的位置是无关的,只是语义上的不同而异。

对于浏览器来说,默认情况下,发送get请求,那么请求参数会附着在地址栏上面,发送post请求,请求参数在请求体,但是这并不意味着所有的情况都是这样。

  1. request.setCharacterEncoding("utf-8")

Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using getReader().

如果请求参数在请求体中,是有中文乱码的,解决方案如上所示。

如果请求参数在地址栏呢?没有乱码问题。前提条件,前端页面使用的是utf-8格式。

地址的书写规则

网络地址。action、img src a href网络路径

1.全路径 http://localhost/app/servlet.

公司里面的开发流程

开发环境:本地的开发环境、局域网的测试环境、公网的生产环境,全路径不合理,但是如果使用全路径,那么你应当保障这些可变的部分必须以配置文件的形式配置下来。properties配置文件

2.相对路径。

相对当前所在页面的一个相对的路径。

比如当前页面是http://localhost/app/form.html

提交的路径是 http://localhost/app/form4

相对路径如何去写呢?form4

这个方式其实不是特别推荐。因为路径会特别依赖于当前路径。

3./开头的路径

写法:/应用名/资源路径 /app/form4.推荐的一种方式。

java:服务器开发、大数据。语言没有特别大的差异。很少会使用java语言去做页面相关的处理。原因在于前端的崛起,前端也有很多的框架,vue、react、angular。java目前的使用场景其实就是去给前端页面提供数据即可。

转发包含

同样是关于页面相关的,所以简单过一遍。

servlet做了逻辑处理,处理完之后需要跳转至一个页面,那么可以怎么来实现呢?

转发:一个组件(源组件)处理部分请求之后,将请求进行进一步转化,转发给另外一个组件(目标组件),后续由两外的组件来进行处理(类似于主动权的交接)

包含:一个组件(源组件)把另外一个组件(目标组件)的内容囊括到自身之中来,然后一并做出响应。(权利没有移交,反而像吸收)

代码上面体现呢?

涉及的全部都是针对的源组件

  1. 对于转发来说,转发后,源组件可以在最终的响应报文中留下响应头,但是无法留下响应体
  2. 对于包含来说, 包含后,源组件不仅可以留下响应头,还可以留下响应体。