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框架中應該優先使用攔截器。