spring boot (二) servlet listener filter interceptor
spring boot 二 servlet listenerfilter interceptor
一般做web开发,使用controller就可以满足大部分的需要,但是有的时候也会用到servlet listener filter 和interceptor等,spring boot中取消了繁杂的xml配置,但是功能并没有减少,所以要对于这些需求,也有相应的解决办法。
servlet
我们知道spingMVC的主servlet 是DispatcherServlet,其默认的url-pattern为“/”,当然springboot也是,spring boog中添加servlet有两种方法,代码注册Servlet和注解自动注册Servlet,spring boot中filter和listener的添加同样也是这两种方法。不过springboot大量使用注解,来简化配置,应该是比较推荐使用注解来自动注册Servlet吧
第一种,通过注解自动注册Servlet,先在启动类上加上注解@ServletComponentScan,来扫描算定义的servlet,
启动类示例:
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class,args);
}
}
示例DemoServlet2.java
@WebServlet(urlPatterns="/gaox/hello",description="测试")
public class DemoServlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponseresp)
throws ServletException, IOException {
// TODO Auto-generatedmethod stub
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("hello ,baby !");
}
}
run as 启动类启动,在浏览器中输入http://localhost:8080/gaox/hello,结果:
第二种,通过代码来注册servlet,新建一个普通的类继承HttpServlet,重写service或doGet 、doPost方法,示例DemoServlet.java:
public class DemoServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
// TODO Auto-generatedmethod stub
request.setCharacterEncoding("utf-8");
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
response.getWriter().print("测试一下");
}
}
然后把自己自定义的Servlet、监听器、过滤器,在启动的时候注册到容器中,示例:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class,args);
}
/**
* 注册自定义的servlet
* @return
*/
@Bean
public ServletRegistrationBean getServletRegistrationBean(){
return new ServletRegistrationBean(new DemoServlet(),"/gaox/demo");
}
/**
* 注册自定义的监听器
* @return
*/
@Bean
public ServletListenerRegistrationBeangetServletListenerRegistrationBean(){
return new ServletListenerRegistrationBean(newDemoListener3());
}
/**
* 注册自定义的过滤器
* @return
*/
@Bean
public FilterRegistrationBean getFilterRegistrationBean(){
FilterRegistrationBean registrationBean=newFilterRegistrationBean();
registrationBean.setFilter(new DemoFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}}
run as 启动类启动,在浏览器中输入http://localhost:8080/gaox/demo,结果:
listener
在java web应用中,listener监听器似乎是必不可少的,常常用来监听servletContext、httpSession、servletRequest等域对象的创建、销毁以及属性的变化等等,可以在这些事件动作前后进行一定的逻辑处理。
而我暂时先说其中三个用来监听域对象的,分别是servletContextListener、httpSessionListener、servletRequestListener。 这三个接口写法上实际是差不多的,都有两个分别代表了该域对象创建时调用和销毁时调用的方法,这三个对象最大的区别应该就是作用域不一样。 servletContext在整个应用启动到结束中生效,启动系统时创建这个对象,整个过程中这个对象是唯一的。 httpSession则是在一个session会话中生效,在一个session被创建直到失效的过程中都起作用,不过一个启动的应用中httpSession对象可以有多个,比如同一台电脑两个浏览器访问,就会创建两个httpSession对象。 而servletRequest是在一个request请求被创建和销毁的过程中生效,每发起一次请求就会创建一个新的servletRequest对象,比如刷新浏览器页面、点击应用的内链等等。
监听器以及过虑器的添加与servlet的添加一样,也是两种方法,通过代码注册与注解自动注册,方法很类似,其实就是注册的方式不同,一种是用注解,别一种就是代码,两种访求的共同点就是都要继承或实现相应的接口,新建一个实例,然后就是用不同的方式注入到容器里。上面已经在代码中体现了怎么把servlet、listener、filter用代码注入到容器中,这里只贴出用注解怎么注册listener、filter,如果想用代码来注册,那就把相应的解去掉,然后在启动的时候用代码把自己自定义的listener、filter实例添加进去即可。
DemoListener.java:
@WebListener
public class DemoListener implements HttpSessionListener {
private Loggerlog=Logger.getLogger(DemoListener2.class);
@Override
public void sessionCreated(HttpSessionEvent se) {
// TODO Auto-generatedmethod stub
log.info("会话范围内的监听器创建/HttpSessionListener");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generatedmethod stub
log.info("会话范围内监听器被销毁/HttpSessionListener");
}
}
DemoListener2.java
@WebListener
public class DemoListener2 implements ServletContextListener {
private Loggerlog=Logger.getLogger(DemoListener2.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generatedmethod stub
log.info("全局的监听器初始化/ServletContextListener");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generatedmethod stub
log.info("全局监听器被销毁/ServletContextListener");
}
}
DemoListener3.java
@WebListener
public class DemoListener3 implements ServletRequestListener {
private Loggerlog=Logger.getLogger(DemoListener2.class);
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generatedmethod stub
log.info("请求作用域内监听器结束被销毁/ServletRequestListener");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
// TODO Auto-generatedmethod stub
log.info("请求作用域内被初始化/ServletRequestListener");
}
}
Filter
@WebFilter(urlPatterns="/*",filterName="demoFilter")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig)throws ServletException {
// TODO Auto-generatedmethod stub
System.out.println("过滤器初始化");;
}
@Override
public void doFilter(ServletRequest request, ServletResponseresponse,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generatedmethod stub
System.out.println("通过过滤器");
chain.doFilter(request,response);
}
@Override
public void destroy() {
// TODO Auto-generatedmethod stub
System.out.println("过滤器衩销毁");
}
}
执行结果:
HandlerInterceptor的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。
配置拦截器也很简单,Spring提供了基础类WebMvcConfigurerAdapter,我们只需要重写
addInterceptors方法添加注册拦截器。实现自定义拦截器只需要3步:
1、创建我们自己的拦截器类并实现 HandlerInterceptor接口。
2、创建一个Java类继承WebMvcConfigurerAdapter,并重写 addInterceptors方法。
2、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。
MyInterceptor.java:
public class MyInterceptor implements HandlerInterceptor{
private Loggerlog=Logger.getLogger(MyInterceptor.class);
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Objectarg2, Exception arg3)
throws Exception {
// TODO Auto-generatedmethod stub
log.info("1>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponsearg1,
Object arg2, ModelAndViewarg3) throws Exception {
// TODO Auto-generatedmethod stub
log.info("1>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
// TODO Auto-generatedmethod stub
log.info("1>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
return true;// 只有返回true才会继续向下执行,返回false取消当前请求
}
}
MyInterceptor2.java
public class MyInterceptor2 implements HandlerInterceptor{
private Loggerlog=Logger.getLogger(MyInterceptor2.class);
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Objectarg2, Exception arg3)
throws Exception {
// TODO Auto-generatedmethod stub
log.info("2>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponsearg1,
Object arg2, ModelAndViewarg3) throws Exception {
// TODO Auto-generatedmethod stub
log.info("2>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
// TODO Auto-generatedmethod stub
log.info("2>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
return true;// 只有返回true才会继续向下执行,返回false取消当前请求
}
}
CustomMVCConfiguration.java:
@Configuration
public class CustomMVCConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// TODO Auto-generatedmethod stub
super.addInterceptors(registry);
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
}
}
run as 启动类后,在浏览器中输入http://localhost:8081/gaox/test3
结果:
有兴趣可以到码云上获取源码仔细研究:https://gitee.com/fox9916/springboot_demo.git