spring拦截器的应用

导火索:发生表单重复提交,数据库中多次插入多条空数据

 

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;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章