scenario

  • Modify the parameters in the request. Encrypt a field (the data that the interface needs to decrypt). Decrypt the field uniformly
  • Request parameters and response results, log/save database
  • Add additional fields to the request parameters (identifying certain systems, etc.)

OncePerRequestFilter

The GET method

GetParameterMap (), which gets only the parameters of the GET request

// Request parameters
parameterMap = httpRequest.getParameterMap();


// This is generic
// Request mode
String requestMethod = httpRequest.getMethod();
String remoteAddr = httpRequest.getRemoteAddr();
int remotePort = httpRequest.getRemotePort();
Copy the code

No modifications are allowed to a locked ParameterMap exception

/ / org. Apache. Catalina. Util. ParameterMap
@Override
    public V put(K key, V value) {
        checkLocked();
        return delegatedMap.put(key, value);
    }
private void checkLocked(a) {
    if (locked) {
        throw new IllegalStateException(sm.getString("parameterMap.locked")); }}/ / org. Apache. Tomcat. Util. Res., StringManager
public String getString(String key) {
        if (key == null){
            String msg = "key may not have a null value";
            throw new IllegalArgumentException(msg);
        }

        String str = null;

        try {
            // Avoid NPE if bundle is null and treat it like an MRE
            if(bundle ! =null) { str = bundle.getString(key); }}catch (MissingResourceException mre) {
            //bad: shouldn't mask an exception the following way:
            // str = "[cannot find message associated with key '" + key +
            // "' due to " + mre + "]";
            // because it hides the fact that the String was missing
            // from the calling code.
            //good: could just throw the exception (or wrap it in another)
            // but that would probably cause much havoc on existing
            // code.
            //better: consistent with container pattern to
            // simply return null. Calling code can then do
            // a null check.
            str = null;
        }

        return str;
    }
    
/ * error code corresponding to the file under the tomcat org. Apache. Catalina. Util. LocalStrings. Properties PropertyResourceBundle bundle will be loaded into memory * / in the service started
parameterMap.locked=No modifications are allowed to a locked ParameterMap

/ / Java. Util. PropertyResourceBundle
private final Map<String,Object> lookup;
public PropertyResourceBundle (Reader reader) throws IOException {
        Properties properties = new Properties();
        properties.load(reader);
        lookup = new HashMap(properties);
    }
public Object handleGetObject(String key) {
    if (key == null) {
        throw new NullPointerException();
    }
    return lookup.get(key);
}
Copy the code

POST way

The request argument for POST is in the request body, and the body argument is in the form of a stream.

ServletInputStream inputStream = httpRequest.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,StandardCharsets.UTF_8);
BufferedReader bfReader = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String line;
while((line = bfReader.readLine()) ! =null){
sb.append(line);
}
System.out.println(sb.toString());
Copy the code

The request body is missing

The filter gets the POST request parameters, but the Controller layer reported an error.

The httpRequest. GetInputStream () can be used only once, use an error again

The InputStream read method has a postion flag inside. The position read by the current stream moves each time it is read, and if it reaches the end, the inputStream. read method returns -1. If you want to read it again, you can call the inputStream. reset method and position will move to the position where mark was called last time. Mark defaults to 0, so you can read it again. MarkSupported determines whether it can be reset. If it is true, it can be reset; if it is false, it cannot be reset. MarkSupported is false and a call to reset is a direct exception. Needs to be read into the InputStream preserved, use HttpServletRequestWrapper for processingCopy the code

Inheritance override method

@Component
@Slf4j
public class ParamFilter extends OncePerRequestFilter {

    @Value("${app.self.name}")
    private String selfName;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {

        RequestParameterWrapper requestWrapper=null;
        String method=request.getMethod();
        if("GET".equalsIgnoreCase(method)){
            try {
                requestWrapper = new RequestParameterWrapper(request, RequestMethod.GET);
                Map<String, String[]> parameterMap = new HashMap<>(requestWrapper.getParameterMap());
                log.info("The get parameter = {}", parameterMap.toString());
                parameterMap.put("selfName".new String[]{selfName});
                requestWrapper.setParameterMap(parameterMap);
            }catch(Exception e){ e.printStackTrace(); }}else if("POST".equals(method)){
            try {
                requestWrapper = new RequestParameterWrapper(request, RequestMethod.POST);
                // Get the body of the POST message
                String body = requestWrapper.getBody();
                JSONObject jsonObject = new JSONObject(body);
                String dataAuthCode = (String) jsonObject.get("selfName");
                if (StringUtils.isNotBlank(dataAuthCode)) {
                    chain.doFilter(request, response);
                } else {
                    jsonObject.put("selfName", selfName); requestWrapper.setBody(jsonObject); }}catch(Exception e){ e.printStackTrace(); }}if(requestWrapper == null) {
            chain.doFilter(request, response);
        } else{ chain.doFilter(requestWrapper, response); }}}Copy the code

Inheritance HttpServletRequestWrapper

public class RequestParameterWrapper extends HttpServletRequestWrapper {

    private String body;

    private Map<String, String[]> parameterMap;

    public RequestParameterWrapper(HttpServletRequest request, RequestMethod method) throws Exception{
        super(request);

        if(RequestMethod.POST.equals(method)){
            StringBuilder stringBuilder = new StringBuilder();
            try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8")); {char[] charBuffer = new char[128];
                int bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead); }}catch (Exception ex) {
                throw ex;
            }
            body = stringBuilder.toString();
        }else if(RequestMethod.GET.equals(method)){ parameterMap=request.getParameterMap(); }}public String getBody(a) {
        return this.body;
    }

    /** * Use * in post mode@param object
     */
    public void setBody(JSONObject object) {
        this.body=object.toString();
    }



    @Override
    public ServletInputStream getInputStream(a) throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public boolean isFinished(a) {
                return false;
            }

            @Override
            public boolean isReady(a) {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {}public int read(a) throws IOException {
                returnbyteArrayInputStream.read(); }}; }@Override
    public Enumeration<String> getParameterNames(a) {
        Vector<String> vector = new Vector<String>(parameterMap.keySet());
        return vector.elements();
    }

    @Override
    public String getParameter(String name) {
        String[] results = parameterMap.get(name);
        return results[0];
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }

    @Override
    public String[] getParameterValues(String name) {
        return parameterMap.get(name);
    }

    public void setParameterMap(Map<String, String[]> parameterMap) {
        this.parameterMap = parameterMap; }}Copy the code