阐明

这个波及到的次要是和前端约定加密形式,我这边被动采纳了jwt形式,起因吗就不解释了。

实现起来大抵思维就是做拦挡,之前尝试了一版注解形式,做了一半想到一个问题。。注解拦挡的参数是曾经绑定之后的了。。要是本人再去解决的话就会十分麻烦。。

起初果决放弃,想了想还是应用过滤不便,想着只有把申请参数改了不就行了,实际上这样的确是可行的,就是有个坑,得同时批改getParamNames办法,不然参数是绑定不了的

先说实现吧

定义一个过滤器

package com.fedtech.common.filter.jwt;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;/** * 将约定的申请头参数应用jwt转化为一般参数,供零碎应用 * * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a > * @date 2021/2/9 * @since 1.0.0 */@Componentpublic class JwtFilter implements Filter {    @Override    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)            throws IOException, ServletException {        ParameterRequestWrapper paramsRequest = new ParameterRequestWrapper((HttpServletRequest) arg0);        String[] secretParams = paramsRequest.getParameterMap().get("secretParam");        if (secretParams == null) {            arg2.doFilter(arg0, arg1);        } else {            arg2.doFilter(paramsRequest, arg1);        }    }    @Override    public void init(FilterConfig arg0) {    }    @Override    public void destroy() {    }}

重写获取参数相干的办法

package com.fedtech.common.filter.jwt;import com.alibaba.fastjson.JSON;import com.fedtech.common.util.StringJsonUtils;import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jws;import io.jsonwebtoken.Jwts;import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.IOUtils;import org.springframework.util.StringUtils;import org.springframework.web.util.WebUtils;import javax.servlet.ReadListener;import javax.servlet.ServletInputStream;import javax.servlet.ServletRequest;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import java.io.ByteArrayInputStream;import java.io.IOException;import java.nio.charset.StandardCharsets;import java.util.*;import static com.fedtech.common.constants.Request.RequestConstants.CONTENT_TYPE;import static org.apache.commons.lang3.StringUtils.equalsAny;import static org.apache.commons.lang3.StringUtils.isNotBlank;/** * 1. 接口申请过滤去除前后空格 * 2. 解析jwt参数 * * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a > * @date 2021/1/26 * @since 1.0.0 */@Slf4jpublic class ParameterRequestWrapper extends HttpServletRequestWrapper {    /**     * 这个东东就是request.getParam()的params     */    private final Map<String, String[]> params = new HashMap<>();    /**     * 解析jwt就是在这边做的,次要思维就是批改params,毕竟官网没提供setParam办法     * 该办法还同时对参数前后空格做了解决     *     * @param request 申请     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    public ParameterRequestWrapper(HttpServletRequest request) {        // 将request交给父类,以便于调用对应办法的时候,将其输入,其实父亲类的实现形式和第一种new的形式相似        super(request);        //将参数表,赋予给以后的Map以便于持有request中的参数        Map<String, String[]> requestMap = new HashMap<>(request.getParameterMap());        //这边拿到和前端约定的参数名        String[] secretParams = requestMap.get("secretParam");        if (secretParams == null) {            return;        }        String secretParam = secretParams[0];        //没有加密参数的话就不解决了        if (isNotBlank(secretParam)) {            //jwt解析一波            Jws<Claims> jws = Jwts.parser()                    .setSigningKey("secret".getBytes(StandardCharsets.UTF_8))                    .parseClaimsJws(secretParam);            //这边只有过滤掉几个不须要的参数就行啦啦啦啦!!!!            jws.getBody().forEach((x, y) -> {                if (!equalsAny(x, "sub", "exp", "lat", "jti", "iat")) {                    requestMap.put(x, new String[]{String.valueOf(y)});                }            });        }        //在这边全副存起来哈!!        this.params.putAll(requestMap);        //这个是div的,去除前后空格        this.modifyParameterValues();    }    /**     * 重写getInputStream办法  post类型的申请参数必须通过流能力获取到值     *     * @return javax.servlet.ServletInputStream     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    @Override    public ServletInputStream getInputStream() throws IOException {        //非json类型,间接返回        if (!super.getHeader(CONTENT_TYPE).equalsIgnoreCase("json")) {            return super.getInputStream();        }        //为空,间接返回        String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);        if (StringUtils.isEmpty(json)) {            return super.getInputStream();        }        log.info("转化前参数:{}", json);        Map<String, Object> map = StringJsonUtils.jsonStringToMap(json);        log.info("转化后参数:{}", JSON.toJSONString(map));        ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));        return new MyServletInputStream(bis);    }    /**     * 将parameter的值去除空格并且空串返回 null值     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    private void modifyParameterValues() {        Set<String> set = params.keySet();        for (String key : set) {            String[] values = params.get(key);            String[] newValues = new String[values.length];            for (int i = 0; i < values.length; i++) {                newValues[i] = values[i].trim();                if (newValues[i].length() <= 0) {                    newValues[i] = null;                }            }            params.put(key, newValues);        }    }    /**     * 这个吗是最次要的,去看mvn解析链的话,在{@link WebUtils#getParametersStartingWith(ServletRequest, String)}这个外面获取参数就是走的这个办法     *     * @return java.util.Enumeration<java.lang.String>     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    @Override    public Enumeration<String> getParameterNames() {        Vector<String> vector = new Vector<>(params.keySet());        return vector.elements();    }    /**     * 重写getParameter 参数从以后类中的map获取     *     * @return java.lang.String     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    @Override    public String getParameter(String name) {        String[] values = params.get(name);        if (values == null || values.length == 0) {            return null;        }        return values[0];    }    /**     * 重写getParameterValues     *     * @return java.lang.String[]     *     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >     * @date 2021/2/9     * @since 1.0.0     */    @Override    public String[] getParameterValues(String name) {//同上        return params.get(name);    }    static class MyServletInputStream extends ServletInputStream {        private final ByteArrayInputStream bis;        public MyServletInputStream(ByteArrayInputStream bis) {            this.bis = bis;        }        @Override        public boolean isFinished() {            return true;        }        @Override        public boolean isReady() {            return true;        }        @Override        public void setReadListener(ReadListener listener) {        }        @Override        public int read() {            return bis.read();        }    }}

这边就说下入口和重点办法吧

SpringMVC源码之参数解析绑定原理 - leanring - 博客园

Debug最初找到获取参数的中央,这个办法是必须重写的,不然绑定的时候是拿不到的