Servlet详解

一、Servlet的生命周期

(1)创建:构造方法

(2)初始化:init()

默认:第一次访问时,完成创建和初始化。

   <!--    

        在web.xml中的servlet标签中配置
        load-on-startup就是在启动服务器时就创建并初始化Servlet对象
        数字越小,优先级越高。   
    -->
    <load-on-startup>1</load-on-startup>

(3)执行:service() 客户端发起请求时执行

(4)销毁:destroy() 服务器关闭时,Servlet被销毁

问题1:Servlet对象创建、初始化并使用完后会销毁吗?

显然,Servlet对象在创建、初始化并使用后不应该销毁。如果使用完(请求处理完)就销毁,那么下次过来请求又得去创建Servlet对象,这样效率并不高!!

我们自始至终都使用同一个Servlet对象去处理请求,如果同时有10个请求过来访问Tomcat服务器,服务器会创建10个线程来处理请求,因为service方法不涉及到全局变量的修改操作,所以也不会有线程安全问题的。

问题2:Servlet对象会被创建及初始化几次?

由问题1,我们可以了解到,Servlet对象只会被创建及初始化一次。之后会驻留在内存当中。

 问题3:Servlet对象是在什么时候创建及初始化的?

Servlet的创建与初始化的时机有两个:

  1. Servlet在第一次被浏览器访问的时候创建与初始化的(目前我们的代码用的就是这种方式,默认就是这种)

  2. Servlet在启动服务器的时候被创建与初始化的(该方式需要做一些配置,告诉Tomcat服务器在启动的时候就创建Servlet对象)

问题4:Servlet对象什么时候销毁?

Servlet对象是由Tomcat服务器创建的,之后就一直驻留在内存中处理请求。直到服务器停止后,Servlet才会被销毁!

二、web.xml配置Servlet的几种方式

        <!--
            1. url-pattern的值是 /字符 的方式
              比如  /UserServlet,那访问该Servlet的时候url这么写:http://ip:port/项目名/UserServlet
        -->
        <url-pattern>/UserServlet</url-pattern>

        <!--
            2. url-pattern的值是 *.do的方式,
              比如 *.do  那访问该Servlet的时候url这么写:http://ip:port/项目名/xxx.do 只要以.do结尾就行
        -->
        <url-pattern>*.do</url-pattern>

        <!--
            3. url-pattern的值是 多级目录的方式
              比如 /user/UserServlet,那访问该Servlet的时候url这么写:http://ip:port/项目名/user/UserServlet
        -->
        <url-pattern>/user/UserServlet</url-pattern>

        <!--
            4. url-pattern的值是 /*,表示拦截所有请求
               那随便写个访问到该项目的url地址,都会访问该Servlet
        -->
        <url-pattern>/*</url-pattern>

        <!--
            5. url-pattern的值是 /,表示拦截所有请求,但是不拦截 jsp文件
               除了访问jsp外,访问其他的资源都会访问到该Servlet
        -->
        <url-pattern>/</url-pattern>

        <!-- 默认欢迎页的设置 -->

        <welcome-file-list>
            <welcome-file>hello.html</welcome-file>
        </welcome-file-list>

三、HttpServletResponse的使用

(1)获取请求方式

req.getMethod();

(2)获取URI

req.getRequestURI();

(3)获取协议及版本号

req.getProtocol();

(4)获取请求头中的数据

req.getHeader(请求头中的key);

(5)获取请求头中的所有key的值

req.getHeaderNames();

(6)获取客户端的IP

req.getRemoteHost();

(7)获取客户端的端口号

req.getRemotePort();

※(8)获取请求参数

req.getParameter(key值);

※(9)获取请求参数,同一个key值对应了多个value

req.getParameterValues(key值);

※(10)获取所有请求参数key值

req.getParameterNames();

※(11)获取请求参数的Map集合

req.getParameterMap();

※(12)设置编码格式

req.setCharacterEncoding("utf-8");

※(13)设置响应体内容类型

resp.setContentType("text/html;charset=utf-8");

TypeMeaning
application/postscriptPostScript file
application/vnd.lotus-notesLotus Notes file
application/vnd.ms-excelExcel spreadsheet
application/vnd.ms-powerpointPowerPoint presentation
application/x-gzipGzip archive
application/x-java-archiveJAR file
application/x-java-serialized-objectSerialized Java object
application/x-java-vmJava bytecode (.class) file
application/zipZip archive
audio/basicSound file in .au or .snd format
audio/midiMIDI sound file
audio/x-aiffAIFF sound file
audio/x-wavMicrosoft Windows sound file
image/gifGIF image
image/jpegJPEG image
image/pngPNG image
image/tiffTIFF image
image/x-xbitmapX Windows bitmap image
text/cssHTML cascading style sheet
text/htmlHTML document
text/plainPlain text
text/xmlXML
video/mpegMPEG video clip
video/quicktimeQuickTime video clip
application/mswordMicrosoft Word document
application/octet-streamUnrecognized or binary data
application/pdfAcrobat (.pdf) file

四、HttpServletResponse的使用

 设置响应头的信息

//修改响应头

resp.setHeader("key", "value");

//添加响应头

resp.addHeader("name", "value");

//下面两行代码是等价的
resp.setContentType("text/html;charset=utf-8");//设置响应的数据类型及解码方式
resp.setHeader("Content-Type", "text/html;charset=utf-8");//设置响应的数据类型及解码方式

五、请求转发和请求重定向

(1)请求转发

//向req对象中存储数据

req.setAttribute("key","value");

//从req对象中获取数据

req.getAttribute("key");

//请求转发

req.getRequestDispatcher("/Servlet2").forward(req,resp);

特点:

  1. 请求转发是一次请求,地址栏地址不变,还是访问第一个Servlet的地址

  2. 请求转发是一次请求,所以转发内的各个Servlet共享一个request对象

  3. 请求转发是Tomcat服务器内部的行为,用户是看不到的

  4. 可以使用req.setAttribute(key,value)和getAttribute(key)实现请求转发内的Servlet的数据的流转

 总结:请求转发可以实现在后端Servlet之间的相互调用,一个请求由一个Servlet处理,转变为了多个Servlet的协同处理。

(2)请求重定向

resp.sendRedirect(req.getContextPath() + "/MainServlet");

特点:

  1. 重定向是两次请求,地址栏信息改变,地址会变成第二次请求的地址

  2. 重定向的地址是浏览器收到第一次请求响应回来的地址,自动跳转的,用户不参与

  3. 重定向的两次请求,request对象是不同的

(3)转发和重定向的区别

请求转发是一次请求,是Tomcat服务器内部的行为,共享同一个request对象。浏览器只需要发一次请求即可将业务处理完毕。

重定向是两次请求,地址栏信息会改变。一般用户的增删改请求会使用重定向的方式来处理请求。目的是保护第一次请求,避免用户因刷新页面造成表单重复提交。

总结:不论是请求转发还是请求重定向,都会涉及到多个Servlet。如果你需要将A Servlet的处理结果要带到B Servlet中去使用,那就使用请求转发。如果A Servlet的处理结果不需要带到B Servlet中去使用,那就使用重定向。

六、Cookie对象

(1)用处

浏览器在发起请求的时候,请求达到服务器,服务器认为本次请求携带的数据比较常用,以后的请求也会用得上,那么服务器就会在响应的时候告诉浏览器,把本次请求的数据给保存起来。然后浏览器以后每次发送请求访问服务器的时候都给带上!而存储这样数据的对象就是Cookie。

(2)总结

  1. 服务器决定哪些数据是以后的请求也会用到的

  2. 服务器以响应的方式告诉浏览器将常用的这些数据存储起来,存储在浏览器端

  3. 浏览器以后每次发送请求的时候需要带上这些存储起来的数据

 (3)性质

  1. Cookie是浏览器端的数据存储技术

  2. 浏览器每次发起请求的时候,请求信息中就包含了Cookie中存储的数据

  3. Cookie不适合大量数据的存储(每个Cookie存储的数据不超过4KB)

  4. 不安全,不适合存储重要的数据到浏览器端

 (4)使用方式

//创建Cookie对象
Cookie cookie = new Cookie("username", username);


//将创建好的Cookie对象创建到响应中
resp.addCookie(cookie);

//其他servlet获取Cookie
Cookie[] cookies = req.getCookies();

/* 设置Cookie对象的存活时间

正数:表示在指定的秒数后过期

负数:表示浏览器一关,Cookie就会被删除(默认是-1)

零:表示马上删除Cookie */
cookie.setMaxAge(60);

//设置可以获取到该Cookie对象的路径范围,若abc为文件夹则只有abc下的资源能访问,若abc为一个资源则只有abc资源能访问

cookie.setPath(req.getContextPath()+"/abc");

//设置域名只要是baidu.com结尾的二级域名都可以访问

cookie.setDomain("baidu.com");

七、HttpSession对象

(1)作用

解决Http协议无状态,实现方式是将数据存储在服务器的Session对象中,将Session的唯一标识JSESSIONID存储到浏览器中的Cookie对象中;一般只存放用户登录的信息或者错误信息。

(2)特点

  1. Session技术解决用户发送不同请求时数据共享的问题

  2. 一个用户在服务器中只会创建一个Session对象。不同用户的Session对象之间是互相独立的

  3. 在服务器中创建Session对象,创建完成后会将Session对象的Id(JSESSIONID)以Cookie的形式保存在客户端(浏览器),用户再次发请求时,会携带该Cookie,也就是JSESSIONID到服务器,服务器会根据该id找到用户的Session对象

  4. 用户JSESSIONID的Cookie丢失或者服务器中存储的Session对象被销毁,服务器接收到用户的请求后,如果找不到对应的Session对象,会重新创建,并将新的JSESSIONID以Cookie的形式保存到浏览器中

  5. 存储JSESSIONID的Cookie不需要手动创建,Session对象创建完成,Tomcat服务器会自动创建Cookie, 将JESSIONID存储在Cookie中响应回浏览器。

  6. Cookie默认的有效期为一次会话,浏览器关闭,Cookie即失效

  7. Session对象在Tomcat服务器的默认有效期为30分钟

  8. Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。

总结:综上所述,默认情况下,浏览器关闭后Cookie被删除,那么再次访问时就不能对应到Session,如果没有关闭浏览器,但是浏览器30分钟内没有操作,那么该Session对象被销毁了,那么存在浏览器中的Cookie也就失去了意义。

(3)使用方式

package com.bjsxt.controller;

import com.bjsxt.pojo.TUser;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        TUser user = new TUser();
        /*
        * 浏览器第一次请求服务器,Cookie中没有JSESSIONID
        * 执行req.getSession();,会创建Session对象,自动将Session对象得到JSESSIONID以Cookie形式存储到浏览器中,再返回session
        *
        * 浏览器再次请求服务器,Cookie中携带JSESSIONID,
        * 执行req.getSession(),会根据JSESSIONID寻找Session对象
        *   1.找到,直接返回session
        *   2.没找到,会创建Session对象,自动将Session对象得到JSESSIONID以Cookie形式存储到浏览器中,再返回session
        *
        * Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。
        * 用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。
        * */

        HttpSession session = req.getSession();

        //向Session对象中存储数据
        session.setAttribute("user",user);
        //从Session对象中获取数据
        session.getAttribute("user");
        //获取JSESSIONID
        String id = session.getId();
        //获取创建时间
        long creationTime = session.getCreationTime();
        //获取最后一次访问时间
        long lastAccessedTime = session.getLastAccessedTime();
        //设置最大不操作时间,单位是秒
        session.setMaxInactiveInterval(600);
        //获取最大不操作时间
        int maxInactiveInterval = session.getMaxInactiveInterval();

        /*
        * 销毁HttpSession对象
        *   1.默认浏览器没有操作30分钟后销毁,可通过配置web.xml文件修改默认销毁的时间
        *       <session-config>
        *           <!--设置Session的超时时间,单位是分钟-->
        *           <session-timeout>10</session-timeout>
        *       </session-config>
        *   2.通过invalidate()方法手动销毁
        * */

        session.invalidate();

    }
}

(4)Cookie和Session的区别

  1. Cookie数据存储在客户端,而HttpSession中的数据存储在服务器

  2. Cookie不安全,而HttpSession是安全的

  3. 单个cookie保存的数据不能超过4KB,很多浏览器都限制一个域名保存cookie的数量

    HttpSession没有容量以及数量的限制, 随着Session中存储的内容增多,会比较占用服务器内存, Session不存放业务数据

  4. Cookie的数据都以字符串的形式保存。Session中可以保存对象

  5. Cookie实现, 如: 记住我 最近浏览商品 网页皮肤 等

  6. Session实现, 如: 登录信息 错误信息 购物车 等

  7. Session依赖于Cookie

 八、ServletContext对象

(1)作用

存储不同的用户也可能会用到相同的数据。

(2)特点

  1. ServletContext对象由Tomcat服务器在启动加载项目的时候完成创建

  2. ServletContext对象一个项目中只有一个,以任意方式获取到的都是同一个

  3. ServletContext对象中保存的数据是所有共享的

(3)使用方式

package com.bjsxt.controller;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/contextServlet")
public class ContextServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取ServletContext对象
        ServletContext servletContext = getServletContext();
        ServletContext servletContext1 = this.getServletContext();
        ServletContext servletContext2 = super.getServletContext();
        ServletContext servletContext3 = req.getServletContext();
        ServletContext servletContext4 = req.getSession().getServletContext();

        //往ServletContext对象中存数据,键值对的方式
        servletContext.setAttribute("name", "root");

        //从ServletContext对象中获取数据
        String name = (String)servletContext.getAttribute("name");

        /*
        * 可以在web.xml中配置一些参数,可以通过ServletContext对象获取。经常出现在框架的底层。
        * <!--配置上下文参数-->
        *   <context-param>
        *       <param-name>name</param-name>
        *       <param-value>admin</param-value>
        *   </context-param>
        * */
        String name1 = servletContext.getInitParameter("name");
     
    }
}

九、域对象

什么是域对象

域对象类似于map集合,可以存放键值对的数据。不同的是域对象中数据的使用有一定的区域范围限制。

三大域对象

request域        对应HttpServeltRequest对象   也叫请求域

Session域       对应HttpSession对象               也叫会话域

application域   对应ServletContext对象          也叫应用域

常用API

setAttribute(key, value) 向域中添加/修改数据,无则添加,有则修改

getAttribute(key) 获取域中的数据

removeAttribute(key) 从域中移除指定key的数据

十、过滤器(Filter)

(1)使用场景

 需要对请求进行相关处理, 处理完成后, 在访问请求的资源。

(2)使用方式

  1. 创建一个类,实现过滤器接口(Filter)

  2. 实现接口中的方法,编写自己的代码

  3. 在web.xml中配置过滤器或通过注解配置

package com.bjsxt.controller;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class CharacterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        //请求之前会经过
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
        //响应之前会经过
    }

    @Override
    public void destroy() {

    }
}

十一、 监听器(Listener)

(1)作用

监听三大域对象的创建、销毁及数据的变更。

(2)特点

  1. 监听方法由tomcat根据监听结果来调用执行

  2. 监听方法中的逻辑代码由我们根据需要编写

(3)使用方式 

监听器的使用步骤:

  1. 创建一个类,实现监听器接口(Listener)

  2. 实现里面的方法

  3. 在web.xml中配置监听器或通过注解配置

<!--
    配置监听器,在服务器启动的时候就会创建监听器对象,监听器生效,一旦符合监听要求,
    tomcat底层会通过反射调用监听器中的方法完成处理
-->
<listener>
    <listener-class>com.bjsxt.listener.MyListener</listener-class>
</listener>

@WebListener

监听器接口:

  1. ServletRequestListenter 监听request对象的创建销毁

  2. ServletRequestAttributeListener监听request域中数据的变更

  3. HttpSessionListener 监听Session对象的创建销毁

  4. HttpSessionAttributeListener 监听Session对象中数据的变更

  5. ServletContextListener 监听ServletContext对象的创建销毁

  6. ServletContextAttributeListener监听ServletContext对象中数据的变更

package com.chen.listener;

import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class MyListener implements ServletRequestListener, ServletRequestAttributeListener,
        HttpSessionListener, HttpSessionAttributeListener, ServletContextListener, ServletContextAttributeListener {
    //监听ServletContext对象中数据的添加
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {

    }
    //监听ServletContext对象中数据的删除
    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {

    }
    //监听ServletContext对象中数据的修改
    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {

    }
    //监听ServletContext对象的初始化
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

    }
    //监听ServletContext对象的销毁
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
    //监听ServletRequest对象中数据的添加
    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request对象中添加的数据!");
    }
    //监听ServletRequest对象中数据的删除
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request对象中删除了数据!");
    }
    //监听ServletRequest对象中数据的修改
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request对象中修改了数据!");
    }
    //监听ServletRequest对象中数据的销毁
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被销毁!");
    }
    //监听ServletRequest对象的初始化
    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被初始化!");
    }
    //监听HttpSession对象中数据的添加
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {

    }
    //监听HttpSession对象中数据的删除
    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {

    }
    //监听HttpSession对象中数据的修改
    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {

    }
    //监听HttpSession对象的创建
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

    }
    //监听HttpSession对象的销毁
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {

    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值