SpringMVC token 防止表单重复提交
来源:互联网 发布:软件设计师考试经验 编辑:程序博客网 时间:2024/05/17 22:23
一、定义注解 Token.Java
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Token {
- boolean save() default false;
- boolean remove() default false;
- }
二、定义token 过滤器 TokenInterceptor.java
- package com.bra.common.web;
- import com.bra.common.web.annotation.Token;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.lang.reflect.Method;
- import java.util.UUID;
- public class TokenInterceptor extends HandlerInterceptorAdapter {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- Method method = handlerMethod.getMethod();
- Token annotation = method.getAnnotation(Token.class);
- if (annotation != null) {
- boolean needSaveSession = annotation.save();
- if (needSaveSession) {
- request.getSession(false).setAttribute("token", UUID.randomUUID().toString());
- }
- boolean needRemoveSession = annotation.remove();
- if (needRemoveSession) {
- if (isRepeatSubmit(request)) {
- return false;
- }
- request.getSession(false).removeAttribute("token");
- }
- }
- return true;
- } else {
- return super.preHandle(request, response, handler);
- }
- }
- private boolean isRepeatSubmit(HttpServletRequest request) {
- String serverToken = (String) request.getSession(false).getAttribute("token");
- if (serverToken == null) {
- return true;
- }
- String clinetToken = request.getParameter("token");
- if (clinetToken == null) {
- return true;
- }
- if (!serverToken.equals(clinetToken)) {
- return true;
- }
- return false;
- }
- }
三、拦截器配置 SpringMVC.xml
- <mvc:interceptor>
- <mvc:mapping path="${adminPath}/**" />
- <bean class="com.bra.common.web.TokenInterceptor" />
- </mvc:interceptor>
四、JSP
- <input type="hidden" name="token" value="${token}"/>
五、Controller
1、请求表单时,生成token
- @RequestMapping(value = "save")
- @Token(remove = true)
- public String save(ReserveField reserveField,
- Model model, RedirectAttributes redirectAttributes) throws ParseException {
- if (!beanValidator(model, reserveField)) {
- return form(reserveField, model);
- }
- reserveFieldService.save(reserveField);
- addMessage(redirectAttributes, "保存场地基本信息成功");
- redirectAttributes.addAttribute("reserveVenue.id",reserveField.getReserveVenue().getId());
- return "redirect:" + Global.getAdminPath() + "/reserve/reserveField/list";
- }
2、保存时,验证token ,remove=true 表示删除同步token
- @RequestMapping(value = "form")
- @Token(save = true)
- public String form(ReserveField reserveField, Model model) throws ParseException {
- //场地列表
- List<ReserveField> fields = reserveFieldService.findList(new ReserveField());
- User user=new User();
- user.setUserType("7");
- List<User> userList = reserveUserService.findList(user);
- model.addAttribute("userList", userList);
- model.addAttribute("reserveField", reserveField);
- model.addAttribute("fields", fields);
- model.addAttribute("venues", reserveVenueService.findList(new ReserveVenue()));
- model.addAttribute("projects", reserveProjectService.findList(new ReserveProject()));
- return "reserve/field/form";
- }
1、SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。
2、继承抽象类HandlerInterceptorAdapter
- package com.kp.spring.interceptor;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- import com.kp.spring.util.SystemUtils;
- /**
- * @author: py
- * @version:2016年10月17日 上午11:28:43
- * com.kp.spring.interceptor.TestInterceptor.java
- * @Desc SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求
- * 并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是
- * 否是购票时间。
- */
- /**
- * 输入:
- * http://localhost:8080/SpringMvcKP/test/test.do
- * 结果:
- 时间:2016-10-22 16:32:15;类:com.kp.spring.interceptor.TestInterceptor;path:/test/test.do
- 时间:2016-10-22 16:32:15;类:com.kp.spring.interceptor.TestInterceptor;contextPath:/SpringMvcKP
- 时间:2016-10-22 16:32:15;类:com.kp.spring.interceptor.TestInterceptor;name:com.kp.spring.controller
- *
- */
- public class TestInterceptor extends HandlerInterceptorAdapter {
- /**
- * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,
- * SpringMVC中的Interceptor拦截器是链式的,可以同时存在 多个Interceptor,
- * 然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在
- * Controller方法调用之前调用。
- * SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返
- * 回值为false,
- * 当preHandle的返回值为false的时候整个请求就结束了。
- */
- @Override
- public boolean preHandle(HttpServletRequest request,
- HttpServletResponse response, Object handler) throws Exception {
- SystemUtils.println(TestInterceptor.class, null, "****1preHandle");
- String path = request.getServletPath();
- String contextPath = request.getContextPath() ;
- SystemUtils.println(TestInterceptor.class, "path", path);
- SystemUtils.println(TestInterceptor.class, "contextPath", contextPath);
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- if(handlerMethod.getMethodAnnotation(ResponseBody.class)!=null){
- //ajax 请求不拦截
- return true;
- }
- // 访问的不是WX下的,直接跳过
- String name = handlerMethod.getBeanType().getPackage().getName();
- SystemUtils.println(TestInterceptor.class, "name", name);
- if (!name.contains("com.oo.project")) {
- return true;
- }
- }
- return true;
- }
- /**
- * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。
- *
- * postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之后,也就是在Controller
- * 的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中
- * 你可以对ModelAndView进行操作。
- * 这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,
- * 这跟Struts2里面的拦截器的执行过程有点像, 只是Struts2里面的intercept方法中要手动的调用
- * ActionInvocation的invoke方法,Struts2中调用ActionInvocation的invoke方法就是调用下
- * 一个Interceptor或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,
- * 要在Interceptor之后调用的内容都写在调用invoke方法之后。
- */
- @Override
- public void postHandle(HttpServletRequest request,
- HttpServletResponse response, Object handler,
- ModelAndView modelAndView) throws Exception {
- SystemUtils.println(TestInterceptor.class, null, "****2postHandle");
- super.postHandle(request, response, handler, modelAndView);
- }
- /**
- * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。
- * 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,
- * 这个方法的主要作用是用于清理资源的,
- * 当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
- */
- @Override
- public void afterCompletion(HttpServletRequest request,
- HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- SystemUtils.println(TestInterceptor.class, null, "****3afterCompletion");
- super.afterCompletion(request, response, handler, ex);
- }
- }
3、两个需拦截的controller
①MyController
- package com.kp.spring.controller;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- @Controller
- public class MyController {
- @RequestMapping("my.do")
- public void my(){
- System.out.println("test my ");
- }
- }
②YouController
- package com.kp.spring.controller;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- @Controller
- @RequestMapping("you")
- public class YouController {
- @RequestMapping("you.do")
- public void you(){
- System.out.println("test you ");
- }
- }
4、配置文件如果是
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/*"/>
- <bean class="com.kp.spring.interceptor.TestInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
浏览器输入:http://localhost:8080/SpringMvcKP/my.do
控制台输出:
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****1preHandle
- test my
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****2postHandle
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****3afterCompletion
浏览器输入:http://localhost:8080/SpringMvcKP/you/you.do
控制台输出:test you
结果:
成功拦截http://localhost:8080/SpringMvcKP/my.do
拦截http://localhost:8080/SpringMvcKP/you/you.do失败5、配置文件如果是
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <bean class="com.kp.spring.interceptor.TestInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
浏览器输入:http://localhost:8080/SpringMvcKP/my.do
控制台输出:
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****1preHandle
- test my
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****2postHandle
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****3afterCompletion
浏览器输入:http://localhost:8080/SpringMvcKP/you/you.do
控制台输出:
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****1preHandle
- test you
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****2postHandle
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****3afterCompletion
结果:
成功拦截http://localhost:8080/SpringMvcKP/you/you.do
成功拦截http://localhost:8080/SpringMvcKP/my.do
6、配置文件如果是,
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/you/*"/>
- <bean class="com.kp.spring.interceptor.TestInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
浏览器输入:http://localhost:8080/SpringMvcKP/my.do
控制台输出:test my
浏览器输入:http://localhost:8080/SpringMvcKP/you/you.do
控制台输出:
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****1preHandle
- test you
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****2postHandle
- 时间:2016-10-22 17:10:46;类:com.kp.spring.interceptor.TestInterceptor;内容:****3afterCompletion
结果:
拦截http://localhost:8080/SpringMvcKP/my.do失败
成功拦截http://localhost:8080/SpringMvcKP/you/you.do
7、配置文件如果是,
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/"/>
- <bean class="com.kp.spring.interceptor.TestInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
浏览器输入:http://localhost:8080/SpringMvcKP/my.do
控制台输出:test my
浏览器输入:http://localhost:8080/SpringMvcKP/you/you.do
控制台输出:test you
结果:
拦截http://localhost:8080/SpringMvcKP/my.do失败
拦截http://localhost:8080/SpringMvcKP/you/you.do失败
原文地址:http://blog.csdn.net/u014520797/article/details/52893474
- SpringMVC token 防止表单重复提交
- SpringMVC token 防止表单重复提交
- token防止表单重复提交
- token-防止表单重复提交
- springmvc中使用token来防止表单重复提交
- SpringMVC token 防止表单重复提交,加上注释,帮助理解
- springMVC中基于token防止表单重复提交
- SpringMVC 防止表单重复提交
- SpringMVC表单防止重复提交
- Springmvc表单防止重复提交
- struts2防止表单重复提交 token
- struts2之防止表单重复提交 token
- 《struts---利用Token防止表单重复提交》
- 运用session token防止表单重复提交
- session token 防止表单重复提交
- php表单加入Token防止重复提交
- structs2 防止表单的重复提交token
- <s:token/>防止表单重复提交
- plus-one
- python---布尔类型赋值,字符串,len(),转义、拼接、替换、文件操作
- 第2章 开始VBA编程的第一步。
- 文章标题
- 端口大全
- SpringMVC token 防止表单重复提交
- A*B Problem II
- convert-sorted-array-to-binary-search-tree
- RN环境配置
- UE4 插件打包后的小技巧(可修改,可隐藏代码等)
- 在arm linux QT开发流程
- 关于字符编码 GB2312,UTF-8,GBK,BIG5
- 创建进程回调函数_阻止打开任何进程
- Maven私服上传 jar包