servlet+过滤器:github:https://github.com/xaioheilj/ServeletCRUDandJSON.git
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。该接口定义了以下3个方法:
- init(FilterConfig) :这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后就会调用这个方法。在这个方法中可以通过 FilterConfig来读取web.xml文件中Servlet过滤器的初始化参数。
- doFilter(ServletRequest, ServletResponse, FilterChain) : 这是完成实际的过滤操作的方法,当客户请求访问与过滤器关联的URL时,Servlet容器先调用该方法。FilterChain参数用来访问后续的过滤 器的doFilter()方法。
- destroy() :Servlet容器在销毁过滤器实例前调用该方法,在这个方法中,可以释放过滤器占用的资源。
Filter的生命周期
Filter的创建和销毁由web服务器控制。
- 服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次,init方法也只会执行一次。
- 拦截到请求时,执行doFilter方法。可以执行多次。
- 服务器关闭时,web服务器销毁Filter的实例对象。
- 缺点是一个过滤器实例只能在容器初始化时调用一次。
1.集中解决中文乱码
public class EncodingFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; request.setCharacterEncoding("UTF-8"); chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { } }
在web.xml中添加映射即可
<filter> <filter-name>EncodingFilter</filter-name> <filter-class>filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.登录验证
public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(true); //启用Session,过滤器从中获取信息 String name = request.getParameter("userName"); String password = request.getParameter("password"); session.setAttribute("userName",name); session.setAttribute("password",password); if ("admin".equals(name) && "123".equals(password)) { request.getRequestDispatcher("addHero.html").forward(request, response); }else{ response.sendRedirect("login.html"); } } }
public class AuthFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String uri = request.getRequestURI(); if (uri.endsWith("login.html") || uri.endsWith("login")) { chain.doFilter(request, response); return; } String userName = (String) request.getSession().getAttribute("userName"); if (null == userName) { response.sendRedirect("login.html"); return; } chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { } }
在web.xml中添加映射即可
<filter> <filter-name>AuthFilter</filter-name> <filter-class>filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
SpringBoot+Interceptor :github:https://github.com/xaioheilj/SpringBoottest1.git
它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
/*过滤器,登录检查*/ /*实现拦截器可以通过继承HandlerInterceptorAdapter类。如果preHandle方法return true,则继续后续处理。*/ public class LoginHandleInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user= request.getSession().getAttribute("loginUser"); if (user == null){ //没有登陆过,不予许直接访问dashboard,并返回到登录页面 request.setAttribute("msg","没有权限,先登录"); request.getRequestDispatcher("/login").forward(request,response); return false; }else { return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
在配置信息注册拦截器
/* *实现拦截器后还需要将拦截器注册到spring容器中,可以通过implements WebMvcConfigurer,覆盖其*addInterceptors(InterceptorRegistry registry)方法。记得把Bean注册到Spring容器中,可以选择*@Component 或者 @Configuration。 */ //@EnableWebMvc //全面接管SpringMVC @Configuration //使用WebMvcConfigurer扩展SpringMVC的功能,所有的WebMvcConfigurer都会一起起作用 public class MyMVCconfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { //浏览器发送/felix请求,到达firstPage页面 registry.addViewController("/felix").setViewName("firstPage"); } @Bean // 将组建注册在容器中 public WebMvcConfigurer wbc(){ //引入静态资源文件,使访问路径直接访问到login页面 WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login"); registry.addViewController("/login").setViewName("login"); registry.addViewController("/main").setViewName("dashboard"); } //注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/user/login","/asserts/**","/webjars/**"); } }; return webMvcConfigurer; } }
过滤器filter和拦截器Interceptor的区别
spring的拦截器和servlet的过滤器有相似之处,都是AOP思想的体现,都可以实现权限检查,日志记录,不同的是适用范围不同:Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器的使用范围就大得多
使用的资源不同:拦截器是属于spring的一个组件,因此可以使用spring的所有资源,对象,如service对象,数据源,事务控制等,而过滤器就不行
深度不同:Filter还在servlet前后起作用。而拦截器能够深入到方法前后,异常抛出前后,因此拦截器具有更大的弹性,所有在spring框架中应该优先使用拦截器。