自定义注解用于数据校验和登录拦截

在日常开发中由于在一些接口需要用到数据校验和登录校验,考虑到如果使用AOP进行的话那么就会对该类中所有的方法进行校验和拦截,直接在方法上面加过于代码的臃肿。所以使用了自定义注解加拦截器加过滤器的形式来进行数据的校验功能

 

首先创建自定义注解的形式,该注解用于方法上面的注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
public @interface ResolvedDexParams {


}

创建拦截器对请求的接口进行拦截

package com.supermap.realestate_gx.districtOffice.annotation;

import com.alibaba.fastjson.JSONObject;
import com.supermap.realestate_gx.districtOffice.model.InternerPlusPackage;
import com.supermap.realestate_gx.districtOffice.model.InternetPlusParams;
import com.supermap.realestate_gx.districtOffice.model.SHARE_LOGIN;
import com.supermap.realestate_gx.districtOffice.service.impl.ShareQueryServiceImpl;
import com.supermap.realestate_gx.districtOffice.util.*;
import com.supermap.wisdombusiness.framework.dao.impl.CommonDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Component
public class DexInterceptor extends HandlerInterceptorAdapter {


    private final Logger logger = LoggerFactory.getLogger(ShareQueryServiceImpl.class);
    @Autowired
    private CommonDao baseCommonDao;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //执行方法之前
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        ResolvedDexParams annotation = method.getAnnotation(ResolvedDexParams.class);
        if (annotation != null){
            String token = request.getHeader("token");
            //校验token值,如果用户没有登录那么就直接校验失败返回信息
            if (StringUtil.isEmpty(token)){
                
            }
            logger.info("获取到用户的token:"+token);
            List<SHARE_LOGIN> dataList = baseCommonDao.getDataList(SHARE_LOGIN.class, "TOKEN = '" + token + "' and EFFECTIVEDATA > to_date('" + StringUtil.getDateParse(new Date()) + "'," + "'yyyy-mm-dd hh24:mi:ss')");
            if (dataList.isEmpty()){
              
            }
            String bodyString = new BodyReaderHttpServletRequestWrapper(request).getBodyString();
//            ServletInputStream inputStream = request.getInputStream();
//            String param = StringUtil.readRaw( inputStream);
            logger.info("正在对传入的数据进行数据检查,当前登录用户的为:"+token);
            if (StringUtil.isEmpty(bodyString)){
              
            }
            InternerPlusPackage data = JSONObject.parseObject(bodyString, InternerPlusPackage.class);
            String requestseq = data.getRequestseq();
            String requestcode = data.getRequestcode();
            InternetPlusParams dataInfo = data.getData();
            if (StringUtil.isEmpty(requestseq) || StringUtil.isEmpty(requestcode) || dataInfo == null){
            
            }
            String xzqdm = dataInfo.getXzqdm();
            if (StringUtil.isEmpty(xzqdm)){
               
            }
            return true;

        }
        return super.preHandle(request, response, handler);
    }



    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //TODO 可以用于对返回的数据加密
        super.afterCompletion(request, response, handler, ex);
    }
}

由于上面的数据是用流的形式发送,在开发中遇到了流只能读取一次的问题,这个使用就使用过滤器进行Request的拷贝解决该问题

public class ReplaceStreamFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(requestWrapper, response);
    }

    @Override
    public void destroy() {

    }
}

用于拷贝请求头的工具类

package com.supermap.realestate_gx.districtOffice.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 存储body数据的容器
     */
    private final byte[] body;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);

        // 将body数据存储起来
        String bodyStr = getBodyString(request);
        body = bodyStr.getBytes(Charset.defaultCharset());
    }

    /**
     * 获取请求Body
     *
     * @param request request
     * @return String
     */
    public String getBodyString(final ServletRequest request) {
        try {
            return inputStream2String(request.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取请求Body
     *
     * @return String
     */
    public String getBodyString() {
        final InputStream inputStream = new ByteArrayInputStream(body);

        return inputStream2String(inputStream);
    }

    /**
     * 将inputStream里的数据读取出来并转换成字符串
     *
     * @param inputStream inputStream
     * @return String
     */
    private String inputStream2String(InputStream inputStream) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset()));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                }
            }
        }

        return sb.toString();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return inputStream.read();
            }
        };
    }
}

在Controller层使用的方法注解都会进行拦截

  @RequestMapping(value = "/test", method = RequestMethod.POST)
    @ResponseBody
    @ResolvedDexParams
    public ResponseVo test(@RequestBody String params){
        return testService.test(test);
    }

 

posted @ 2021-07-23 10:29  小福gui  阅读(198)  评论(0)    收藏  举报