SpringMVC拦截器
首先是快速搭建一个springMVC项目
- 新建项目
- mvn依赖导入
- 添加webMoudle
- 添加Tomcat运行环境.在配置tomcat时ApplicationContext置为"/"
- 配置Artfact的lib
- 配置WEB-INF配置文件(记得添加乱码过滤)
- 配置springmvc-servlet文件(applicationContext文件)最好把JSON乱码也配置了
- 新建控制器
以上的配置文件均在百宝箱中
package com.kang.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping("/test")
public String test(){
System.out.println("成功执行");
return "success";
}
}

好的开始是成功的一半。
来创建拦截器类myInterceptor
首先我们要实现HandlerInterceptor接口

接口下有三个方法,我们来实现这三个方法
-
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):
在控制器方法执行前调用。
返回 true 表示继续执行后续的拦截器和控制器方法;返回 false 表示中断执行,不再调用后续的拦截器和控制器方法。
可以用于权限验证、日志记录等。
-
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):
在控制器方法执行后,但在视图渲染前调用。
可以用于修改 ModelAndView 对象,添加额外的数据等。
-
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):
在整个请求处理完成后调用,无论是否发生异常。
可以用于资源清理、日志记录等。
package com.kang.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 {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("====================执行前======================");
return true;//设置为true会执行下一个拦截器,相当于放行。
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("====================执行后======================");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("====================清理======================");
}
}
我们在使用在前要对他进行一些简单的配置在applicationContext中
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/><!--/**代表所有文件夹所有请求-->
<bean class="com.kang.config.myInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
”mvc:mapping”标签来锁定要过滤的类
下面注册的bean就是我们自定义的拦截器。

执行结果为这个说明了三个函数的执行顺序preHandle在程序执行之前进行的过滤、postHandle执行之后、afterCompletion最后执行。
所以执行的顺序就是:preHandle->services业务->postHandle->afterCompletion
其中perHandle有一个返回值为boolean类型,决定了它是否要执行下面的语句,当我们把它置为false时

当我们在执行页就只剩下perHandle里面的操作了,由此我们可以在这个基础上添加一个登陆页面,当他的返回值不为true的时候就不会执行下面的语句,话不多说,我们直接干;
首先我们要明确两个页面一个是登录页面一个是首页,在第一阶段我们首先来完成注册页面的表单的设计还有主页。
在login.jsp中
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<input type="text" name="name">
密码:<input type="text" name="pwd">
<input type="submit" value="提交">
</form>
建一个表单,这个就是登录页面,负责信息的获取,他要把得到的信息发送到后台的login函数进行逻辑判断决定是否转跳到首页
@RequestMapping("/login")
public String login(HttpSession session, String name, String pwd){
session.setAttribute("userInfo",name);
session.setAttribute("pwd",pwd);
<!--逻辑判断,校验-->
return "main";
}
用session来储存登录信息。这里先省略一些逻辑判断,之后设计main页面,里面的内容可以随便一点
因为我们的两个页面都是创建在web-inf下的页面只有servlet才能转跳到,所以设计转跳的逻辑
@RequestMapping("/main")
public String main(){
return "main";
}
@RequestMapping("/goLogin")
public String login(){
return "login";
}
在index页面设计超链接转跳,先转到后台,再由后台转到首页或者登录页面。
<body>
<h1><a href="${pageContext.request.contextPath}/goLogin">登录页面</a></h1>
<h1><a href="${pageContext.request.contextPath}/main">首页</a></h1>
</body>
测试一下,我们先把perHandle设置为false,拦截一些服务

当我们通过超链接访问login页面时会被拦截,只输出了执行前
当我们把perHandle置为true时

成功转跳到了login.jsp页面,提交后就到了首页,这里有一个不合理的地方就是无论我们提交什么都会到首页(main.jsp)
这里我们就进入第二阶段来利用拦截器实现转跳的判断。
刚才在拦截器置为false的时候容易卡在后端界面内,所以我们尽量做true判断来设计logininterceptor,
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
if(request.getRequestURI().contains("goLogin")){
return true;//在登录页面
}
if(session.getAttribute("userInfo")!=null){
return true;//已经登陆过
}
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request,response);//失败返回到登陆页面
return false;
}
这里的逻辑判断是,已经在login页面就继续执行,让用户进入login页面,或者用户已经登录过了session不为空就可以放行
但是如果请求首页但是没有登陆过就会被重定向到登录页面,从而实现拦截
在我们可以在Controller中加一级访问@RequestMapping(“/user”),然后再user的基础上再配置拦截器,这样就可以拦截指定的请求。
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/><!--/**代表所有文件夹所有请求-->
<bean class="com.kang.config.myInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/user/**"/><!--/**代表所有文件夹所有请求-->
<bean class="com.kang.config.loginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
配置applicationContext.xml就完成了,记得修改请求改为“${pageContext.request.contextPath}/user/main"加上user,包括controller中的所有请求,index超链接中的也加上/user,注册页面login的表的action也要改,确保成功过滤。

这样我们在index中直接访问首页的时候就会被打回。
我们在拦截器里面给login的重定向函数放行就能成功转跳了
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
if(request.getRequestURI().contains("goLogin")){
return true;//在登录页面
}
if(request.getRequestURI().contains("login")){
return true;
}
if(session.getAttribute("userInfo")!=null){
return true;//已经登陆过
}
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request,response);//失败返回到登陆页面
return false;
}
这样我们在啊提交以后就可以成功转跳到首页,这时我们返回index也可以直接访问首页。
我们下一步实现在首页显示用户名还有退出登录的操作
首先是显示用户名。我们在controller里面添加一个Model实现值传递,再在前端页面获取。
关于退出登录的操作我直接移除session里面的属性
@RequestMapping("/login")
public String login(HttpSession session, String name, String pwd ,Model model ){
model.addAttribute("name",name);
session.setAttribute("userInfo",name);
session.setAttribute("pwd",pwd);
return "main";
}
@RequestMapping("/out")
public String out(HttpSession session){
session.removeAttribute("userInfo");
return "main";
}
<body>
<h2>首页</h2>
<h2>用户名为:${name}</h2>
<h2><a href="${pageContext.request.contextPath}/user/out">退出登录</a> </h2>
</body>
在这里要记得配置过滤器避免中文乱码(web.xml)
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

成功!拦截器很类似于我们的Sping中的aop事件织入技术,拦截器在那个基础上方便了我们的开发,不同导入织入的包,在这里也可以感受到我们Spring的AOP的思想。

546

被折叠的 条评论
为什么被折叠?



