1.拦截器原理图
过滤器--->Dispatcherservlet-->拦截器
拦截器:是类似于过滤器的拦截机制,过滤器用来拦截servlet的一些资源Disathcherservlet是springmvc的中央拦截器是springmvc内置实现的,必须实现接口HandlerInterceptor,该接口中有三个方法preHandle()在action之前,postHandle()在action之后,aftercompletion()当所有action调用完成之后,一般只用preHandle(),拦截器放回true可执行,返回false不可执行;
2.自定义拦截器
1.定义拦截器
在类中实现接口HandlerInterceptor
public class MyInteractor implements HandlerInterceptor {
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
return true;
}
}
3.配置自定义拦截器
<mvc:interceptors>
<!-- 自定义拦截器 -->
<mvc:interceptor>
<!-- path="/inter" 表示拦截的资源 path="/**"拦截所有的action -->
<mvc:mapping path="/inter"/>
<bean class="cn.etspringmvc.lesson05.MyInteractor"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.防止表单重复提交
一、在数据库添加唯一字段
在数据库建表的时候在ID字段添加主键约束,账号,名称的信息添加唯一性约束。确保数据库只可以添加一条数据。
此方法最有效的防止了数据重复提交。
二、用js为添加禁用
当用户提交表单之后,可以使用js将提交按钮隐藏(disable属性),防止用户多次点击按钮提交数据。
注意:如果客户端禁止使用js,则此方法无效。
三、使用Post/Redirect/Get
Post/Redirect/Get简称PRG,是一种可以防止表单数据重复提交的一种Web设计模式,像用户刷新提交响应页面等比较典型的重复提交表单数据的问题可以使用PRG模式来避免。例如:当用户提交成功之后,执行客户端重定向,跳转到提交成功页面。
注意:PRG设计模式并不适用所有的重复提交情况,比如:
1)由于服务器响应缓慢,用户刷新提交POST请求造成的重复提交。
2)用户点击后退按钮,返回到数据提交界面,导致的数据重复提交。
3)用户多次点击提交按钮,导致的数据重复提交。
4)用户恶意避开客户端预防多次提交手段,进行重复数据提交。
四、使用session设置令牌
产生页面时,服务器为每次产生的Form分配唯一的随机标识号,并且在form的一个隐藏字段中设置这个标识号,同时在当前用户的Session中保存这个标识号。当提交表单时,服务器比较hidden和session中的标识号是否相同,相同则继续,处理完后清空Session,否则服务器忽略请求。
注意:恶意用户可利用这一性质,不断重复访问页面,以致Session中保存的标识号不断增多,最终严重消耗服务器内存。可以采用在Session中记录用户发帖的时间,然后通过一个时间间隔来限制用户连续发帖的数量来解决这一问题。
2.防止表单重复提交原理图
5.防止表单重复提交代码实现
自定义标签中:
<%@ tag language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@attribute name="tokenName" required="false"%>
<%
String ranStr=UUID.randomUUID().toString();
String key=(tokenName==null?"myToken":tokenName);
session.setAttribute(key,ranStr);
%>
<input type="hidden" name='<%=key%>' value='<%=ranStr %>'/>
controller层:
@Autowired
MoneyDaoImpl dao;
@RequestMapping(value="/tm",method=RequestMethod.GET)
public String reg(Integer money,OutputStream out) throws IOException{
dao.trasnateMoney(money);
out.write(("lostedmoney is:"+dao.selectMoney()).getBytes());
return null;
}
持久层:
@Repository
public class MoneyDaoImpl {
@Autowired
JdbcTemplate jdbc;
public void trasnateMoney(int money){
String sql="update mymoney set lostedmoney=lostedmoney-"+money+" where id=2";
jdbc.execute(sql);
}
public int selectMoney(){
String sql="select lostedmoney from mymoney where id=2";
int lostedMoney=jdbc.queryForObject(sql,Integer.class);
return lostedMoney;
}
}
接口实现类:
public class TokenInteractor implements HandlerInterceptor {
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String myToken=request.getParameter("myToken");
Object myToken1=request.getSession().getAttribute("myToken");
//验证重复提交
if(myToken!=null){
//重复提交
if(myToken1==null){
return false;
}else{
if(myToken.equals(myToken1)){
request.getSession().removeAttribute("myToken");
return true;
}else{
return false;
}
}
}else{
return true;
}
}
}
JSP页面:
<!-- 引入自定义标签 -->
<%@taglib tagdir="/WEB-INF/tags" prefix="my" %>
<form action="${pageContext.request.contextPath }/tm">
扣款:<input type="text" name='money'>
<my:token></my:token>
<input type="submit" value="提交">
</form>
配置防止重复提交拦截器:
<mvc:interceptors>
<!-- 防止重复提交的拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/tm"/>
<bean class="cn.etspringmvc.lesson05.TokenInteractor"></bean>
</mvc:interceptor>
</mvc:interceptors>