Servlet基础知识点回顾(二)

本文最后更新于:2021年10月4日 下午

本篇文章用于简易回顾Servlet基础知识,并阅读自己之前项目里写过的一些Servlet代码。

Servlet基础知识点回顾(二)

知识点补充:

关于Cookie和Session

简单了解Session、Cookie、Token

Servlet中的Cookie和Session

一个Web应用,通过Cookie和Session验证用户身份(简要概述):

客户端首次访问服务端,服务端登记客户端信息后,给客户端发送Cookies,其中包含Session相关信息,以及一些其它的信息。

客户端下次访问时,将Cookies发送给客户端,客户端通过解析Cookies来获取客户端信息并进行Session匹配。

服务端:Servlet通过获取请求中的Cookies、编辑响应中要发送的Cookies,来CRUD Cookies。

客户端:保存管理服务端发送过来的Cookies。

Servlet中Cookie的常见操作

// Servlet的Cookie类中的常见字段

// 键值对
private String name;
private String value;

// 保存时间
private int maxAge = -1;
// Servlet对Request中Cookies的基本操作

public class CookieDemoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        PrintWriter out = resp.getWriter();
        // 从请求中获取cookies
        Cookie[] cookies = req.getCookies();
        // 判断cookies是否存在
        if (cookies != null) {
            // 显示req中cookies的信息
            for (Cookie cookie : cookies) {
                out.write(cookie.getName() + " " + cookie.getValue() + "\n");
            }
            // 查看上次登录时间
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("latestLoginTime")) {
                    long latestLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(latestLoginTime);
                    out.write(date.toString());
                }
            }
        } else {
            // 在该项目中,永远不会进入这个分支,因为最开始访问网站时已经进行了一次Cookie的传输了
            out.write("第一次进入本服务器");
        }
        // 更新上次登录时间:新建一个cookie,里面存储访问时间,并放入响应对象
        Cookie timeCookie = new Cookie("latestLoginTime", String.valueOf(System.currentTimeMillis()));
        timeCookie.setMaxAge(24 * 60 * 60); // 设置这个cookie的存活时间
        resp.addCookie(timeCookie);

    }

}

Cookie的限制

一个Cookie只能保存一个信息

一些浏览器会给Cookies数量设置上限

Cookie大小一般会限制为4kb

服务端无法实时地编辑已发送至客户端的Cookies,只能设置Cookies的生命周期来进行删除

Session

服务端:保存客户端的会话信息,并通过Session来CRUD。

客户端:通过秘钥,与服务端进行会话的匹配。

每个Web应用会给每个浏览器创建一个Session对象,只要浏览器没有关闭,Session会一直存在 (多数情况下,服务端也能主动注销Session)

补充:

Session的动态生命周期

Session的使用场景

保存用户登录信息

保存购物车信息

在整个web应用中经常使用的数据,一般都会保留在session中

Servlet中Session的常见操作

public class SessionDemoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 			IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        HttpSession session = req.getSession();
        session.setAttribute("sessionName", "SessionDemoServlet"); // get不做演示
        String sessionId = session.getId();
        if (session.isNew()) {
            resp.getWriter().write("Session元素创建成功,ID: " + sessionId);
        } else {
            resp.getWriter().write("Session已存在,ID: " + sessionId);
        }
    }
}

XML配置Session

<!-- 设置Session的默认失效时间 -->
<session-config>
    <!-- 
		10个时间单位后服务端内的Session失效,时间单位为分钟。
		在常见Web应用中,Session注销前会被保存至数据库。
		下次获取SessionId时,重新激活这个Session,达到减少服务器负载的效果。
	-->
    <session-timeout>10</session-timeout>
    <cookie-config>
        <!-- 设置sessionId的Cookie在浏览器的保存时间,单位为秒 -->
        <max-age>6000</max-age>
    </cookie-config>
</session-config>

关于JSP和Servlet

JSP执行过程

JSP的本质就是Servlet-api的一种实现类。

在Tomcat中,JSP被转换称为一个Servlet实现类,并且进行了编译之后才转换为Web容器能处理的Servlet对象。

由此可见,Servlet是Java Web编程中实现动态网页的一种重要手段,是Java各种Web的框架的底层核心。

关于MVC架构和Servlet

一般来说,Servlet处于控制层(Controller),专注于接收用户请求、发送响应给用户、重定向或转发视图层中的视图等一系列控制操作,很少涉及业务逻辑代码,虽然在原则上说,Servlet可以完成Web应用的几乎所有功能,但为了代码解耦,让架构中的每个层级分工明确,Servlet一般仅作用于Controller层。

Servlet过滤器

用来过滤从Web容器(客户端到Web容器再到Servlet)中获得的数据(例如HttpServletRequest、HttpServletRequest),比如过滤无用信息、统一字符编码、过滤用户等级、登录验证等操作。

过滤器实例:统一字符编码

// 注解配置过滤器的方式
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/filterTest/*")
public class EncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 在web服务器开始运行时,过滤器就会生成
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        System.out.println("过滤器生效前");
        // 放行数据,并继续执行可能存在的下一个过滤器
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("过滤器已生效");
    }

    @Override
    public void destroy() {
        //web服务器关闭后销毁过滤器
    }
}
<!-- 使用xml配置的方式 -->
<filter>
    <filter-name>CodeFilter</filter-name>
    <filter-class>com.rootzwy.controller.EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CodeFilter</filter-name>
    <url-pattern>/filterTest/*</url-pattern>
</filter-mapping>

Servlet监听器

顾名思义,监听Servlet中的一系列操作,如Session、ServletContext等,与过滤器不同,监听器一开始就定义了一系列元素的监听器接口,继承自EventListener接口

监听器实例:监听Session创建

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

// 使用注解配置监听器的方式
@WebListener()
public class FilterTestListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {

    public FilterTestListener() {
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        /* This method is called when the servlet context is initialized(when the Web application is deployed). */
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        /* This method is called when the servlet Context is undeployed or Application Server shuts down. */
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        /* Session is created. */
        HttpSession session = se.getSession();
        System.out.println(session.getAttribute(""));
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        /* Session is destroyed. */
    }

    @Override
    public void attributeAdded(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is added to a session. */
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is removed from a session. */
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is replaced in a session. */
    }
}
<!-- 在xml中配置监听器的方式 -->
<listener>
    <listener-class>com.rootzwy.controller.FilterTestListener</listener-class>
</listener>