spring-boot笔记-Servlet、过滤器、监听器(三)

当使用spring-Boot时,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。 Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。本篇文章主要写springboot中如何定义Servlet、Filter、Listener、Interceptor等。具体这几个区别暂时不展开讲,我在文中也简单做一下陈述。

一、Servlet

在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)

  1. 代码注册通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。 也可以通过实现 ServletContextInitializer 接口直接注册。【不过多讨论】
  2. 在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。
@EnableConfigurationProperties({GhProperties.class})
@SpringBootApplication
@ServletComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

下面来自定义我们的Servlet代码:

import javax.servlet.ServletConfig;
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;
import java.io.PrintWriter;

/**
 * Created by gonghao on 2017/6/2.
 */
@WebServlet(name = "ghServlet",urlPatterns = "/gh/*",loadOnStartup = 1)
public class GhServlet extends HttpServlet {

    @Override
    public void init(ServletConfig servletConfig){
        //初始化做点事情
        System.out.println("初始化servlet:GhServlet,输出日志以示存在!");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello,My name is : GhServlet</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

有几点稍微注意下:

  • name = "ghServlet"不指定name的情况下,name默认值为类全路径,即com.example.demo.utils.servlet.GhServlet.

  • urlPatterns = "/gh/*"为需要拦截的内容。

  • loadOnStartup = 1 意思是项目启动时加载,默认的是用到该Servlet才会加载,这样我们就可以在启动的时候看到输出日志了。

    效果如下:
    这里写图片描述

这里写图片描述
在线人数那个先忽略,是为了演示Listener的。我们前台发起了请求,符合我们的urlPatterns = /gh/*,所以该请求被拦截到,输出到页面一堆文字(忽略中文乱码)。

有个问题说明一下:DispatcherServlet 默认拦截“/”,GhServlet 拦截“/gh/*,那么在我们访问 http://localhost:8080/gh/11的时候系统是按照:“匹配的优先级是从精确到模糊,符合条件的Servlet并不会都执行”。

二、Filter

由于我们采取注解方式,Servlet、Filter、Listener都可以直接采用。这里直接展示自定义Filter的代码:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Created by gonghao on 2017/6/2.
 */
@WebFilter(filterName = "ghFilter",urlPatterns = "/*",asyncSupported = true)
public class GhFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化自定义Filter:GhFilter");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String uri = httpServletRequest.getRequestURI();
        System.out.println("打印请求URI:"+uri);
        if(!uri.contains("gh")){
            httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/gh");
            return;
        }
        filterChain.doFilter(servletRequest,servletResponse);

    }

    @Override
    public void destroy() {
        System.out.println("销毁...");
    }
}

明确一点:我们的Filter的拦截范围是“/*”,我们这里在Filter里面做了一些事情:如果请求不包含/gh,我们就给它重定向到 path+/gh,由于前面我们定义了Servlet拦截了/gh/*,所以现在是无论我们在请求里面写了什么东西,都会被重定向到刚刚Servlet那个显示页面上。
例如我们 访问 http://localhost:8080/hello,来看下前后台的显示:
这里写图片描述
这里写图片描述
我们可以看到,hello的请求被Filter过滤器拦截到,重定向到/gh,又被我们的Servlet所处理,doPost到输出页面。

三、Listener

Listener的类型有好几个,我们这里简单实现一个HttpSessionListener,也做一个简单的在线人数统计。
我们先对我们的过滤器Filter改造一下,把刚刚那个拦截注释掉,只留下 创建HttpSession那一步:

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();//这句话要留着,不然不会创建session,我们的HttpSessionListener也就触发不了了。
//        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
//        String uri = httpServletRequest.getRequestURI();
//        System.out.println("打印请求URI:"+uri);
//        if(!uri.contains("gh")){
//            httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/gh");
//            return;
//        }
        filterChain.doFilter(servletRequest,servletResponse);

    }

自定义Listener的代码:

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by gonghao on 2017/6/2.
 */
@WebListener
public class GhListener implements HttpSessionListener{

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext app = httpSessionEvent.getSession().getServletContext();
        int count = 0;
        String countStr = app.getAttribute("onLineCount")+"";
        if(!"null".equals(countStr)){
            count = Integer.parseInt(countStr);
        }
        count++;
        app.setAttribute("onLineCount", count);
        System.out.println("在线人数:"+count);

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext app = httpSessionEvent.getSession().getServletContext();
        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
        count--;
        System.out.println("在线人数:"+count);
        app.setAttribute("onLineCount", count);
    }
}

我们分别在IE和chrome访问时,查看后台数据统计:
这里写图片描述
忽略中间的那段,是做拦截器的输出,我们可以看到人数统计会增加,而且同一个浏览器新开窗口会算成一个session。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值