深入Servlet

#深入Servlet

1. servlet类中静态代码块、构造方法、代码块、init()、destroy()方法执行顺序

1.1. 举例:

public class MyServlet extends HttpServlet {

    static {
        System.out.println("静态代码块被执行了");
    }

    public MyServlet() {
        System.out.println("构造方法被执行了");
    }

    {
        System.out.println("代码块被执行了");
    }

    public void init() throws ServletException {
        System.out.println("init() 方法被执行了");
    }
    
    public void destroy() throws ServletException {
        System.out.println("destroy() 方法被执行了");
    }
    // 省略其他方法
}

当 Servlet 容器启动时,它会加载 MyServlet 类并创建它的实例。在这个过程中,上述四个部分的代码将按照以下顺序执行:

  1. 在类加载时,静态代码块会被执行一次。在容器加载 MyServlet 类时被执行。
  2. 在构造方法被执行前,代码块会被执行一次。
  3. 当 MyServlet 实例被创建时,它的构造方法会被执行。会在容器创建 MyServlet 实例时被执行。
  4. 在 MyServlet 实例被创建完成后,Servlet 容器会调用它的 init() 方法,完成 Servlet 的初始化工作。会在容器创建 MyServlet 实例并调用它的 init() 方法时被执行。
  5. 在服务器正常停止后Servlet容器会调用它的 destroy() 方法,完成 Servlet 的结束工作。

2. 客户(浏览器)发起http访问http://localhost:8080/web0327/hello服务端做了什么事情。

  1. 服务器开启(监听)
  2. 客户端发起http://localhost:8080/web0327/hello访问
  3. tomcat服务器接收到,对应的是web0327项目提供服务,通过web0327项目中web.xml (DD)知道对应 url-pattern , HelloServlet提供服务。

  0. 创建ServletContext对象,读取DD中的context-param信息
  1. 创建HelloServlet对象 new HelloServlet()
  2. 调用init方法
  3. 创建HelloServlet对应的ServletConfig对象 (读取init-param信息)
  4. 开启新的线程,调用Servlet接口中定义的service()
  5. 找到HttpServlet中定义的service方法。
  6. service(HttpServletRequest request, HttpServletResponse response)
  7. 创建HttpServletRequest request, HttpServletResponse response,把这两个对象,传入到service方法中
  8. HttpServlet中的service方法,根据请求的方式,相应调用doGet()
  9. 最后被调用的是:HelloServlet类中定义的doGet(HttpServletRequest request, HttpServletResponse response)
  10. 开发者而言,只要在doGet(HttpServletRequest request, HttpServletResponse response)中,对request, response操作
  11. 操作后的结果,返回给浏览器

  1. HelloServlet对象,是“单例”多线程的。
    所有的访问,http://localhost:8080/web0327/hello
    tomcat都会开启一个“新线程”让HelloServlet对象,
    并且,为这次访问,创建HttpServletRequest request, HttpServletResponse response对象,调用
    service(HttpServletRequest request, HttpServletResponse response)把2个对象传递。
    当这次请求结束了,这个线程也释放,HttpServletRequest request, HttpServletResponse response存在堆上,
    通过线程上的service方法栈上进行引用。这个两个对象,随着请求的结束而被放弃引用(销毁)

  2. N次http访问,到HelloServlet,
    请问HelloServlet对象有几个? 始终1个“单例”
    HttpServletRequest和HttpServletResponse对象,有几个? N,tomcat会为每次访问,创建request和response对象

  3. 解释转发(请求分派)
    request.getRequestDispatcher(url).forward(request, response); 相当于这次访问没有结束,而是调用url的资源,把request, response传递过去重定向(再次发起新的请求)
    response.sendDirect(url); 说明本次请求结束了。提醒浏览器再次发起新的访问url
    所以,就再次发起新的请求到url, tomcat重新为这次请求开启新线程,创建request, response对象!

3. 简述request获取请求参数的几种方式

  1. URL查询参数(Query Parameters):可以通过ServletRequest对象的getQueryString()方法获取URL中的查询参数,也可以通过ServletRequest对象的getParameter()方法获取指定查询参数的值。例如:
String queryString = request.getQueryString();
String paramValue = request.getParameter("paramName");
  1. 请求体中的表单(Form Data):可以通过ServletRequest对象的getParameter()方法获取表单参数的值,也可以通过ServletRequest对象的getParameterValues()方法获取多个表单参数的值。例如:
String paramValue = request.getParameter("paramName");
String[] paramValues = request.getParameterValues("paramName");
  1. 请求体中的JSON数据:可以通过ServletRequest对象的getReader()方法获取请求体的字符流,然后使用第三方JSON库解析JSON数据。例如:
BufferedReader reader = request.getReader();
JsonObject json = new Gson().fromJson(reader, JsonObject.class);
  1. 请求头中的参数(Header Parameters):可以通过ServletRequest对象的getHeader()方法获取指定请求头的值,也可以通过ServletRequest对象的getHeaderNames()方法获取所有请求头的名称。例如:
String headerValue = request.getHeader("headerName");
Enumeration<String> headerNames = request.getHeaderNames();
  1. 请求体中的文件(File Uploads):可以使用第三方文件上传组件(如Apache Commons FileUpload)来处理文件上传,并通过ServletRequest对象的getPart()方法获取上传文件的Part对象。例如:
ServletFileUpload fileUpload = new ServletFileUpload();
List<FileItem> items = fileUpload.parseRequest(request);
for (FileItem item : items) {
    if (!item.isFormField()) {
        Part filePart = request.getPart(item.getFieldName());
    }
}
  1. 请求体中的原始数据(Raw Data):如果请求体中的数据不是表单数据或JSON数据,而是原始数据(例如XML或文本数据),可以通过ServletRequest对象的getReader()方法或getInputStream()方法获取请求体的字符流或字节流。例如:
BufferedReader reader = request.getReader();
InputStream inputStream = request.getInputStream();

需要注意的是,在使用getReader()方法获取字符流之后,就不能再使用getInputStream()方法获取字节流了,因为这两种方法只能获取一次请求体中的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奕の辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值