SpringMVC:拦截器
概述;
过滤器和拦截器的区别? (拦截器是AOP思想的具体应用)
过滤器:
servlet规范中的一部分,任何javaWeb工程都可以使用
在<url -parttern>中配置了/*后,可以对所有访问的资源进行拦截
拦截器:
拦截器是SpringMVC自己的,只有使用了SpringMVC框架的工程才能使用
拦截器只会拦截访问控制器(controller)的方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
拦截器是AOP思想的具体应用
自定义拦截器:
必须实现HandlerIntercepter接口
小Demo,
1.基础环境搭建
1.1配置web.xml,(配置DispatcherServlet,请求分发器)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
1.2,在spring的容器中(applicationContext)配置拦截器配置
<!--拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!--包括这个请求下面的所有请求--> <mvc:mapping path="/**"/> <bean class="com.king.config.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
1.2.1完整版spring容器基础配置,applicationContext
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.king.controller"/> <!--静态资源过滤,不让静态资源走视图解析器--> <mvc:default-servlet-handler/> <!--注解驱动:dispatcherServlet,DefaultAnnotationHandlerMapping:处理器,作用在类上,处理请求映射的,相应的用户请求传递给相应的Controller类中 AnnotationMethodHandlerAdapter:适配器,作用在方法上,功能与上相似、找相应的方法--> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jps/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> <!--解决json乱码问题--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="failOnEmptyBeans" value="false"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!--拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!--包括这个请求下面的所有请求--> <mvc:mapping path="/**"/> <bean class="com.king.config.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors> </beans>
2.编写一个Controller类,用来模拟用户请求
package com.king.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/t1") public String test(){ System.out.println("testController方法执行了"); return "OK"; } }
3.编写实现拦截器接口类,HandlerInterceptor
package com.king.config; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { //return true;执行下一个拦截器,放行 //return false;不执行下一个拦截器 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("=======处理前========"); return true; } //此处一般写拦截日志 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("=======处理后========"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("=======清理========"); } }
小demo,利用springmvc的拦截器实现用户登录,当非法登陆时时会被拦截器拦截
非法登录:跳过登录请求直接进入用户页面(待更)
拦截器作用,让非法请求不执行
1.jsp页面
1.1首页(未登录的页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <h1><a href="${pageContext.request.contextPath}/user/goLogin">登录</a></h1> <h1><a href="${pageContext.request.contextPath}/user/main">首页</a></h1> </body> </html>
1.2登陆页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登陆</title> </head> <body> <%--在web-inf下的所有页面或者资源,只能通过controller,或者servlet进行访问--%> <form action="${pageContext.request.contextPath}/user/login" method="post"> 用户名:<input type="text" name="name"><div>${error}</div> 密码:<input type="text" name="pwd"> <input type="submit" value="提交"/> </form> </body> </html>
1.3登录成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>欢迎</title> </head> <body> <h1>欢迎!<span>${name}</span></h1> <p> <a href="${pageContext.request.contextPath}/user/goOut">注销</a> </p> </body> </html>
2.Contrller层
package com.king.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @Controller @RequestMapping("/user") public class LoginController { @RequestMapping("/main") public String main(){ return "main"; } @RequestMapping("/goLogin") public String login(){ return "login"; } @RequestMapping("/login") public String login(HttpSession session, String name, String pwd, Model model){ String username="king"; session.setAttribute("nameInfo",name); if (name.equals(username)){ model.addAttribute("name",name); return "main"; } model.addAttribute("error","错误请重新输入"); return "login"; } @RequestMapping("/goOut") public String login(HttpSession session){ session.removeAttribute("nameInfo"); return "login"; } }
3.拦截器
注:拦截器,必须实现HandlerInterceptor接口,重写里面的方法
package com.king.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @Controller @RequestMapping("/user") public class LoginController { @RequestMapping("/main") public String main(){ return "main"; } @RequestMapping("/goLogin") public String login(){ return "login"; } @RequestMapping("/login") public String login(HttpSession session, String name, String pwd, Model model){ String username="king"; session.setAttribute("nameInfo",name); if (name.equals(username)){ model.addAttribute("name",name); return "main"; } model.addAttribute("error","错误请重新输入"); return "login"; } @RequestMapping("/goOut") public String login(HttpSession session){ session.removeAttribute("nameInfo"); return "login"; } }
小结:
1.拦截器时springmvc的,只有走SpringMVC框架的请求才会被拦截
2.想使用拦截器,必须实现HandlerInterceptor接口
HandlerInterceptor的方法:
preHandle
调用时间:Controller方法处理之前
执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行
若返回false,则中断执行,注意:不会进入afterCompletion
postHandle
调用前提:preHandle返回true
调用时间:Controller方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作
执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序倒着执行。
备注:postHandle虽然post打头,但post、get方法都能处理
afterCompletion
调用前提:preHandle返回true
调用时间:DispatcherServlet进行视图的渲染之后
多用于清理资源