在SpringBootApplication上使用@ServletComponentScan注解后,
Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。
过滤器
默认使用的4个
在启动打印出来的日志里有:
- Filter ‘requestContextFilter‘ configured for use
- Filter ‘hiddenHttpMethodFilter‘ configured for use
- Filter ‘characterEncodingFilter‘ configured for use
- Filter ‘formContentFilter‘ configured for use
优先级
低位值意味着更高的优先级。自定义Filter,避免和默认的Filter优先级一样,不然会冲突。
作用(使用场景)
- 比如用户验证。
- 如果涉及页面跳转,filter就不适合 前后端分离的情况。
实例
启动类 加上 注解
@ServletComponentScan
自定义的filter
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter(urlPatterns = {"/api/*"}) public class LoginFilter implements Filter { /** * 容器加载的时候调用 */ @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init loginFilter"); } /** * 请求被拦截的时候进行调用 */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter loginFilter"); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String username = request.getParameter("username"); if ("xdclass".equals(username)) { filterChain.doFilter(request, response); }else { response.sendRedirect("/index.html"); // 重定向 } } @Override public void destroy() { System.out.println("destroy loginFilter"); } }
测试
添加controller的访问方法。
@GetMapping(value="/api/v1/account") public Object account(){ params.put("money", "1000"); return params; }
访问 http://localhost:8080/api/v1/account?username=xdclass
{ "money": "1000" }
测试通过。
自定义servlet
例子
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; @WebServlet(urlPatterns = {"/v1/api/test/customs"}, name = "userServlet") public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().print("custom sevlet"); resp.getWriter().flush(); resp.getWriter().close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
启动类 加上 @ServletComponentScan , 和 过滤器的使用 很像。
监听器
自定义Listener(常用的监听器 servletContextListener、httpSessionListener、servletRequestListener)。
@WebListener public class RequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { // TODO Auto-generated method stub System.out.println("======requestDestroyed========"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("======requestInitialized========"); } 、 }
拦截器
1、老方法,jdk8之前
继承 WebMvcConfigurerAdapter
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class CustomOldWebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/");
super.addInterceptors(registry);
}
2、jdk8之后的新方法
使用 implements WebMvcConfigurer
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configurationpublic class CustomWebMvcConfigurer implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginIntercepter()) .addPathPatterns("/api/login/**"); WebMvcConfigurer.super.addInterceptors(registry); }}
3、以上添加了拦截器,现在 给出自定义的拦截器。
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginIntercepter implements HandlerInterceptor{ /** * 进入controller方法之前 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("LoginIntercepter------->preHandle"); // String token = request.getParameter("access_token"); // // response.getWriter().print("fail"); return HandlerInterceptor.super.preHandle(request, response, handler); } /** * 调用完controller之后,视图渲染之前 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("LoginIntercepter------->postHandle"); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } /** * 整个完成之后,通常用于资源清理 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("LoginIntercepter------->afterCompletion"); HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
小结
- 是基于函数回调 doFilter(),而Interceptor则是基于AOP思想。
- Filter在只在Servlet前后起作用,而Interceptor能够深入到方法前后、异常抛出前后等。
- 依赖于Servlet容器即web应用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境。
- 在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
- Filter和Interceptor的执行顺序 过滤前->拦截前->action执行->拦截后->过滤后。
原文地址:https://www.cnblogs.com/wuyicode/p/11251983.html