您的位置:首页 > 编程语言 > Java开发

SpringBoot中Servlet&Listener&Filter的应用

2017-01-06 13:28 671 查看
在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册:
一、代码注册通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。 
二、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

下面首先通过第一种方式验证:
1、添加一个servlet类:
package com.shf.springboot.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = -4186518845701003231L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet1");
resp.setContentType("text/html");

resp.getWriter().write("Servlet1");
}

@Override
public void init() throws ServletException {
super.init();
System.out.println("Servlet1 loadOnStart");
}
}

2、添加一个Java配置类,主要进行servlet配置:
package com.shf.springboot.config;
import javax.servlet.Servlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.shf.springboot.servlet.Servlet1;
import com.shf.springboot.servlet.Servlet3;
@Configuration
public class ServletConfigure {
@Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean
servletRegistrationBean=new ServletRegistrationBean(new Servlet1(), "/servlet1");
return servletRegistrationBean;
}
}
3、启动服务验证,发出请求:



同时控制台



4、如果需要此servlet能够在启动应用时直接加载启动,则修改如下:
@Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean servletRegistrationBean=new ServletRegistrationBean(new Servlet1(), "/servlet1");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}

5、启动服务查看控制台:



再次请求仅打印servlet1



第一种方式配置直接通过ServletRegistrationBean的方式注册bean对象完成注册,springboot中ServletRegistrationBean提供相对比较灵活的配置,不仅仅是loadOnStartup的设置。那么第二种方式是否更加习惯呢,在之前的springmvc中正式通过注解配置,这也是servlet3版本以后的特性。下面就开始验证:
1、首先再次添加2个servlet:
package com.shf.springboot.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns="/servlet2",loadOnStartup=1)
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = -4186518845701003231L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2");
resp.setContentType("text/html");

resp.getWriter().write("Servlet2");
}

@Override
public void init() throws ServletException {
super.init();
System.out.println("Servlet2 loadOnStart");
}
}
package com.shf.springboot.servlet;
import java.io.IOException;
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 org.springframework.boot.web.servlet.ServletContextInitializer;
@WebServlet(urlPatterns="/servlet3")
public class Servlet3 extends HttpServlet {//implements ServletContextInitializer
private static final long serialVersionUID = -4186518845701003231L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet3");
resp.setContentType("text/html");

resp.getWriter().write("Servlet3");
}
@Override
public void init() throws ServletException {
super.init();
System.out.println("Servlet3 loadOnStart");
}
}
两个servlet仅servlet2启动加载,另一个非启动加载。

2、此时还需要在启动类添加servlet扫描注解@ServletComponentScan:
package com.shf.SpringBoot1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import com.shf.springboot.controller.ServerConfig2;

@SpringBootApplication
@EnableConfigurationProperties({ServerConfig.class,ServerConfig2.class})
@ComponentScan(basePackages={"com.shf.SpringBoot1","com.shf.springboot.*"})
@ServletComponentScan(basePackages={"com.shf.springboot.*"})
public class App

extends SpringBootServletInitializer //这个类的作用与在web.xml中配置负责初始化Spring应用上下文的监听器作用类似,如果需要打成war部署在tomcat下则需要
{
@Autowired
ServerConfig serverConfig;
public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);

}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(App.class);
}
}

3、此时即可启动服务,先查看控制台:



说明两种方式不同的配置模式,同样的效果,下面对3个servlet分别请求,观察控制台:







4、以上能够看出servlet的配置已经如期望生效,那么对应的filter以及listener呢,下面添加一个listener统计每个请求的请求时长、一个过滤器过滤所有的请求地址:
监听:
package com.shf.springboot.servlet;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
/**
* 监听每个请求的运行时长
* @description TODO
* @author song
*/
@WebListener
public class PerforationStatListener implements ServletRequestListener {
private static final String START = "Start";

/**
* 请求建立
*/
@Override
public void requestInitialized(ServletRequestEvent servletrequestevent) {
HttpServletRequest request = (HttpServletRequest) servletrequestevent.getServletRequest();
request.setAttribute(START, System.nanoTime());
System.out.println(request.getRequestURI()+"进入监听");
}

/**
* 请求销毁
*/
@Override
public void requestDestroyed(ServletRequestEvent servletrequestevent) {
HttpServletRequest request = (HttpServletRequest) servletrequestevent.getServletRequest();
long start = (Long)request.getAttribute(START);
long ms = (System.nanoTime() - start)/1000;
String uri = request.getRequestURI();
//1秒=1000豪秒 、1毫秒=1000微秒、 1微秒=1000毫微秒
System.out.println("请求"+uri+"耗时:"+ms+"微秒");
}
}
过滤器:
package com.shf.springboot.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter(filterName="myFilter",urlPatterns="/*")
public class MyFilter implements Filter {

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

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("执行过滤操作");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("过滤器初始化");
}
}

5、启动服务验证:



此时请求servlet3



通过此图也不难发现servlet、filter、listener的执行顺序:
listener的requestInitialized()-->servlet的init()-->filter的doFilter()-->servlet的doGet()-->listener的requestDestroyed()

注:以上不仅在开发环境下通过main函数启动服务验证通过,同时通过jar方式采用内置tomcat、以及自定义tomcat容器下war包部署均正常访问、过滤、监听。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息