转载自MarsWang的博客(https://www.cnblogs.com/wangbin2188/p/9199452.html)
spring boot中支持使用java Web三大组件(servlet、listener和filter),但是坑比较多,主要是spring boot内嵌tomcat和独立tomcat服务器有一些细节上的不同,踩完之后,特有此记。
一、spring boot内嵌服务器(注解方式)
1.listener实现(@WebListener)
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Autowired
private AppMetaService appMetaService;
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
Map<String, String> keyMap = appMetaService.getKeyMap();
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
servletContext.setAttribute("keyMap",keyMap);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}
2.filter实现(@WebFilter)
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 在servlet过滤器中触发getSession方法,一次编写,多处使用
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.getSession(true);
filterChain.doFilter(request, servletResponse);
}
@Override
public void destroy() {
}
}
3.servlet实现(@WebsServlet)
@WebServlet(urlPatterns = "/my1")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是自己写的servlet get");
req.getSession().setAttribute("mydemo","张三");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是自己写的servlet");
req.getSession().setAttribute("mydemo","张三");
}
}
4.内嵌服务器支持(@ServletComponentScan)
Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。唯一需要的就是在项目的入口类中加一个注解@ServletComponentScan,顾名思义,它会扫描所有的
@WebServlet、@WebFilter、@WebListener完成对象的注入。
@SpringBootApplication
@ServletComponentScan
public class DataboardApplication {
public static void main(String[] args) {
SpringApplication.run(DataboardApplication.class, args);
}
}
到此为止,简洁明了,不废话,本地测试成功,直接上tomcat服务器。
二、独立tomcat服务器
最大的坑来了,在本地跑的很正常的程序,在服务器上跑不动,最奇怪的是有些接口能用,有些不能用,经过多方观察,发现用到servlet、listener和filter的都挂了。
搜了很多资料之后,还是在spring boot 2.01的文档中找到这么一句话:
Tip
@ServletComponentScan has no effect in a standalone container, where the container’s builtin
discovery mechanisms are used instead.
翻译一下就是@ServletComponentScan这个注解在独立tomcat服务器不可用。
只好退求其次,采用@Bean注入的方式
1.对应的监听器代码
@Component
public class MyHttpSessionListener implements HttpSessionListener {
@Autowired
private AppMetaService appMetaService;
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
Map<String, String> keyMap = appMetaService.getKeyMap();
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
servletContext.setAttribute("keyMap",keyMap);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}
2.对应过滤器代码
@Component
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 在servlet过滤器中触发getSession方法,一次编写,多处使用
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.getSession(true);
filterChain.doFilter(request, servletResponse);
}
@Override
public void destroy() {
}
}
3.启动类代码
@SpringBootApplication
public class DataboardApplication {
@Bean
public ServletListenerRegistrationBean sessionHandler() {
return new ServletListenerRegistrationBean<>(new MyHttpSessionListener());
}
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean myFilter = new FilterRegistrationBean(new MyFilter());
myFilter.addUrlPatterns("/*");
return myFilter;
}
public static void main(String[] args) {
SpringApplication.run(DataboardApplication.class, args);
}
}
直接在启动类中将对应web组件的bean注入或者使用@Component注解自动扫描都可以。避免了@ServletComponentScan在独立的web容器中没有生效的问题。