導火索:發生表單重複提交,數據庫中多次插入多條空數據
1.springmvc的配置文件xml的相關的配置的位置要注意,攔截器的配置位置必須放置在掃描controller的配置後面,否則不能啓用攔截方法。
<!--掃描@Controller--> <context:component-scan base-package="boss.net.controller"> </context:component-scan>
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="boss.net.controller.Interceptor.SameUrlDataInterceptor"/> </mvc:interceptor> </mvc:interceptors>
2.攔截器中的方法先判斷controller的方法是否有相應的註解,如果沒有註解,直接返回true;
如果有註解,再判斷session存的url和參數是否相同,如果不同返回true,如果相同返回false;
package boss.net.controller.Interceptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * 一個用戶 相同url 同時提交 相同數據 驗證 * 主要通過 session中保存到的url 和 請求參數。如果和上次相同,則是重複提交表單 * @author Administrator * */ public class SameUrlDataInterceptor extends HandlerInterceptorAdapter { private final static Logger logger = LoggerFactory.getLogger(SameUrlDataInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ //System.out.println("###########攔截器preHandle#####################"); logger.info("###########攔截器preHandle#####################"); logger.info("#############session:"+request.getSession()); try { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); SameUrlData annotation = method.getAnnotation(SameUrlData.class); if (annotation != null) { if (repeatDataValidator(request))//如果重複相同數據 return false; else return true; } return true; } else { return super.preHandle(request, response, handler); } }catch (Exception e){ e.printStackTrace(); return false; } } /** * 驗證同一個url數據是否相同提交 ,相同返回true * @param httpServletRequest * @return */ public boolean repeatDataValidator(HttpServletRequest httpServletRequest) throws IOException { // System.out.println("###########攔截器repeatDataValidator#####################"); //logger.info("###########攔截器repeatDataValidatore#####################"); RequestWrapper myRequestWrapper = new RequestWrapper((HttpServletRequest) httpServletRequest); String params = myRequestWrapper.getBody(); // BufferedReader streamReader = new BufferedReader( new InputStreamReader(httpServletRequest.getInputStream(), "UTF-8")); // StringBuilder responseStrBuilder = new StringBuilder(); // String inputStr; // while ((inputStr = streamReader.readLine()) != null) // responseStrBuilder.append(inputStr); //Map<String ,String> map1 = JSON.parseObject(Base64.decode(responseStrBuilder.toString()),Map.class); //String userToken = map1.get("token"); //String params=responseStrBuilder.toString(); //String params= JsonMapper.toJsonString(httpServletRequest.getParameterMap()); //logger.info("攔截器repeatDataValidatore:請求入參轉換字符串:"+params); String url=httpServletRequest.getRequestURI(); Map<String,String> map=new HashMap<String,String>(); map.put(url, params); String nowUrlParams=map.toString();// Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData"); if(preUrlParams==null)//如果上一個數據爲null,表示還沒有訪問頁面 { httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams); return false; } else//否則,已經訪問過頁面 { if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+數據和本次url+數據相同,則表示城府添加數據 { return true; } else//如果上次 url+數據 和本次url加數據不同,則不是重複提交 { httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams); return false; } } } }
3.攔截器的判斷是否重複提交的方法中,第一次使用的是獲取請求的輸入流來判斷的,出現了不能流不能重複讀的問題
解決方法:在攔截器之前加上了過濾器,將流轉換成字節緩存下來,再把讀取流的bufferedReader.close()
package boss.net.controller.Interceptor; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; public class RequestWrapper extends HttpServletRequestWrapper { private final String body; public RequestWrapper(HttpServletRequest request) throws IOException { super(request); StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try { InputStream inputStream = request.getInputStream(); if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer = new char[128]; int bytesRead = -1; while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { stringBuilder.append(charBuffer, 0, bytesRead); } } else { stringBuilder.append(""); } } catch (IOException ex) { throw ex; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { throw ex; } } } body = stringBuilder.toString(); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); ServletInputStream servletInputStream = new ServletInputStream() { public boolean isFinished() { return false; } public boolean isReady() { return false; } public void setReadListener(ReadListener readListener) {} public int read() throws IOException { return byteArrayInputStream.read(); } }; return servletInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } public String getBody() { return this.body; } }