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

 

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