前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >屏蔽词过滤器

屏蔽词过滤器

作者头像
阿超
发布2022-08-17 19:44:04
6140
发布2022-08-17 19:44:04
举报
文章被收录于专栏:快乐阿超快乐阿超

黑发不知勤学早,白首方恨读书迟。 ——颜真卿

我们可能想使用本地配置词库、过滤器的方式去做全局屏蔽词处理

这里针对三种参数情况

1.requestParam传参:http://localhost:8080/test?keywords=屏蔽词2号

2.requestBody传参:请求体内传json格式的数据,请求头的Content-Typeapplication/json

3.pathvariable传参:http://localhost:8080/test/屏蔽词3号

这三种应该概括了绝大多数情况下参数传递与接收

代码如下:

首先是过滤器

代码语言:javascript
复制
package com.ruben.simplescaffold.filter;


import com.alibaba.fastjson.JSON;
import com.ruben.simplescaffold.filter.wrappers.RequestWrapper;
import com.ruben.simplescaffold.filter.wrappers.ResponseWrapper;
import com.ruben.simplescaffold.utils.sensitive.SensitiveWordUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

/**
 * 屏蔽词过滤器
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/8/6 17:10
 */
@Slf4j
@Component
@WebFilter(filterName = "SensitiveWordFilter", urlPatterns = "/**")
public class SensitiveWordFilter implements Filter {

    @Resource
    private SensitiveWordUtils sensitiveWordUtils;

    /**
     * The <code>doFilter</code> method of the Filter is called by the container
     * each time a request/response pair is passed through the chain due to a
     * client request for a resource at the end of the chain. The FilterChain
     * passed in to this method allows the Filter to pass on the request and
     * response to the next entity in the chain.
     * <p>
     * A typical implementation of this method would follow the following
     * pattern:- <br>
     * 1. Examine the request<br>
     * 2. Optionally wrap the request object with a custom implementation to
     * filter content or headers for input filtering <br>
     * 3. Optionally wrap the response object with a custom implementation to
     * filter content or headers for output filtering <br>
     * 4. a) <strong>Either</strong> invoke the next entity in the chain using
     * the FilterChain object (<code>chain.doFilter()</code>), <br>
     * 4. b) <strong>or</strong> not pass on the request/response pair to the
     * next entity in the filter chain to block the request processing<br>
     * 5. Directly set headers on the response after invocation of the next
     * entity in the filter chain.
     *
     * @param request  The request to process
     * @param response The response associated with the request
     * @param chain    Provides access to the next filter in the chain for this
     *                 filter to pass the request and response to for further
     *                 processing
     * @throws IOException      if an I/O error occurs during this filter's
     *                          processing of the request
     * @throws ServletException if the processing fails for any other reason
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        long startTime = System.nanoTime();

        // 过滤
        RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest, sensitiveWordUtils, null, null);
        String bodyString = RequestWrapper.BodyHelper.getBodyString(requestWrapper);

        String uri = URLDecoder.decode(requestWrapper.getRequestURI(), StandardCharsets.UTF_8.displayName());
        if (sensitiveWordUtils.isContainSensitiveWord(uri, SensitiveWordUtils.MAX_MATCH_TYPE)) {
            requestWrapper.getRequestDispatcher(sensitiveWordUtils.replaceSensitiveWord(uri, SensitiveWordUtils.MAX_MATCH_TYPE, "0")).forward(requestWrapper, response);
            return;
        }
        // 执行
        chain.doFilter(requestWrapper, responseWrapper);

        // 获取response返回的内容并重新写入response
        String result = responseWrapper.getResponseData(response.getCharacterEncoding());
        response.getOutputStream().write(result.getBytes());

        log.info("method:{}", requestWrapper.getMethod());
        log.info("uri:{}", requestWrapper.getRequestURI());
        log.info("parameterMap:{}", JSON.toJSONString(requestWrapper.getParameterMap()));
        log.info("bodyString:{}", bodyString);
        log.info("responseCode:{}", responseWrapper.getStatus());
        log.info("result:{}", result);
        log.info("timeCost:{}", (System.nanoTime() - startTime) / (1000.0 * 1000.0) + "ms");
    }
}

中间穿插了几个类:

第一个是屏蔽词过滤处理的工具类

代码语言:javascript
复制
package com.ruben.simplescaffold.utils.sensitive;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 敏感词过滤
 *
 * @author chenming
 * @version 1.0
 * @since 2014年4月20日 下午4:17:15
 */
@Slf4j
@Component
public class SensitiveWordUtils {
    public static final String REPLACE_CHAR = "*"; // 替换后的字符
    public static int MIN_MATCH_TYPE = 1;      //最小匹配规则
    public static int MAX_MATCH_TYPE = 2;      //最大匹配规则
    @SuppressWarnings("rawtypes")
    private static Map sensitiveWordMap = null;
    @Value("${sensitive.path}")
    private String sensitivePath;

    public SensitiveWordUtils() {
    }

    /**
     * 初始化敏感词库
     */
    @PostConstruct
    void init() {
        sensitiveWordMap = SensitiveWordInit.getInstance().initKeyWord(sensitivePath);
    }

    /**
     * 判断文字是否包含敏感字符
     *
     * @param txt       文字
     * @param matchType 匹配规则 1:最小匹配规则,2:最大匹配规则
     * @return 若包含返回true,否则返回false
     * @author chenming
     * @since 2014年4月20日 下午4:28:30
     */
    public boolean isContainSensitiveWord(String txt, int matchType) {
        boolean flag = false;
        for (int i = 0; i < txt.length(); i++) {
            int matchFlag = this.CheckSensitiveWord(txt, i, matchType); //判断是否包含敏感字符
            if (matchFlag > 0) {    //大于0存在,返回true
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 获取文字中的敏感词
     *
     * @param txt       文字
     * @param matchType 匹配规则&nbsp;1:最小匹配规则,2:最大匹配规则
     * @return 匹配的敏感词
     * @author chenming
     * @since 2014年4月20日 下午5:10:52
     */
    public Set<String> getSensitiveWord(String txt, int matchType) {
        Set<String> sensitiveWordList = new HashSet<>();

        for (int i = 0; i < txt.length(); i++) {
            int length = CheckSensitiveWord(txt, i, matchType);    //判断是否包含敏感字符
            if (length > 0) {    //存在,加入list中
                sensitiveWordList.add(txt.substring(i, i + length));
                i = i + length - 1;    //减1的原因,是因为for会自增
            }
        }

        return sensitiveWordList;
    }

    /**
     * 替换敏感字字符
     *
     * @param txt         字符串
     * @param matchType   匹配规则
     * @param replaceChar 替换字符,默认*
     * @author chenming
     * @since 2014年4月20日 下午5:12:07
     */
    public String replaceSensitiveWord(String txt, int matchType, String replaceChar) {
        String resultTxt = txt;
        Set<String> set = getSensitiveWord(txt, matchType);     //获取所有的敏感词
        Iterator<String> iterator = set.iterator();
        String word;
        String replaceString;
        while (iterator.hasNext()) {
            word = iterator.next();
            replaceString = getReplaceChars(replaceChar, word.length());
            resultTxt = resultTxt.replaceAll(word, replaceString);
        }

        return resultTxt;
    }

    /**
     * 获取替换字符串
     *
     * @param replaceChar 要替换的字符串
     * @param length      长度
     * @return 替换后的字符串
     * @author chenming
     * @since 2014年4月20日 下午5:21:19
     */
    private String getReplaceChars(String replaceChar, int length) {
        StringBuilder resultReplace = new StringBuilder(replaceChar);
        for (int i = 1; i < length; i++) {
            resultReplace.append(replaceChar);
        }

        return resultReplace.toString();
    }

    /**
     * 检查文字中是否包含敏感字符,检查规则如下:<br>
     *
     * @param txt        需要检测的词
     * @param beginIndex 开始下标
     * @param matchType  匹配规则
     * @return 如果存在,则返回敏感词字符的长度,不存在返回0
     * @author chenming
     * @since 2014年4月20日 下午4:31:03
     */
    @SuppressWarnings({"rawtypes"})
    public int CheckSensitiveWord(String txt, int beginIndex, int matchType) {
        boolean flag = false;    //敏感词结束标识位:用于敏感词只有1位的情况
        int matchFlag = 0;     //匹配标识数默认为0
        char word;
        Map nowMap = sensitiveWordMap;
        for (int i = beginIndex; i < txt.length(); i++) {
            word = txt.charAt(i);
            nowMap = (Map) nowMap.get(word);     //获取指定key
            if (nowMap != null) {     //存在,则判断是否为最后一个
                matchFlag++;     //找到相应key,匹配标识+1
                if ("1".equals(nowMap.get("isEnd"))) {       //如果为最后一个匹配规则,结束循环,返回匹配标识数
                    flag = true;       //结束标志位为true
                    if (SensitiveWordUtils.MIN_MATCH_TYPE == matchType) {    //最小规则,直接返回,最大规则还需继续查找
                        break;
                    }
                }
            } else {     //不存在,直接返回
                break;
            }
        }
        if (matchFlag < 2 || !flag) {        //长度必须大于等于1,为词
            matchFlag = 0;
        }
        return matchFlag;
    }

}

这个工具类需要初始化加载词库,因此我们还有一个初始化的类

代码语言:javascript
复制
package com.ruben.simplescaffold.utils.sensitive;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 初始化敏感词库,将敏感词加入到HashMap中,构建DFA算法模型
 *
 * @author : chenming
 * @since 2014年4月20日 下午2:27:06
 */
public class SensitiveWordInit {
    private volatile static SensitiveWordInit lazyMan;//volatile避免指令重排
    private static boolean SINGLE_SIGN = false;//红绿等解决通过反射创建对象(反编译可以破解该方法)
    @SuppressWarnings("rawtypes")
    public HashMap sensitiveWordMap;

    private SensitiveWordInit() {
        synchronized (SensitiveWordInit.class) {
            if (!SINGLE_SIGN) {
                SINGLE_SIGN = true;
            } else {
                throw new RuntimeException("不要试图使用反射破坏单例");
            }
        }
    }

    //双重检测锁模式的  懒汉式单例    DCL懒汉式
    public static SensitiveWordInit getInstance() {
        if (lazyMan == null) {
            lazyMan = new SensitiveWordInit();//不是一个原子性操作
        }
        return lazyMan;
    }

    /**
     * @author chenming
     * @since 2014年4月20日 下午2:28:32
     */
    @SuppressWarnings("rawtypes")
    public Map initKeyWord(String filePath) {
        try {
            //读取敏感词库
            Set<String> keyWordSet = readSensitiveWordFile(filePath);
            //将敏感词库加入到HashMap中
            addSensitiveWordToHashMap(keyWordSet);
            //spring获取application,然后application.setAttribute("sensitiveWordMap",sensitiveWordMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Collections.emptyMap();
        }
        return sensitiveWordMap;
    }

    /**
     * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br>
     * 中 = {
     * isEnd = 0
     * 国 = {<br>
     * isEnd = 1
     * 人 = {isEnd = 0
     * 民 = {isEnd = 1}
     * }
     * 男  = {
     * isEnd = 0
     * 人 = {
     * isEnd = 1
     * }
     * }
     * }
     * }
     * 五 = {
     * isEnd = 0
     * 星 = {
     * isEnd = 0
     * 红 = {
     * isEnd = 0
     * 旗 = {
     * isEnd = 1
     * }
     * }
     * }
     * }
     *
     * @param keyWordSet 敏感词库
     * @author chenming
     * @since 2014年4月20日 下午3:04:20
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void addSensitiveWordToHashMap(Set<String> keyWordSet) {
        sensitiveWordMap = new HashMap(keyWordSet.size());     //初始化敏感词容器,减少扩容操作
        String key;
        Map nowMap;
        Map<String, String> newWorMap;
        //迭代keyWordSet
        for (String s : keyWordSet) {
            key = s;    //关键字
            nowMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++) {
                char keyChar = key.charAt(i);       //转换成char型
                Object wordMap = nowMap.get(keyChar);       //获取

                if (wordMap != null) {        //如果存在该key,直接赋值
                    nowMap = (Map) wordMap;
                } else {     //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
                    newWorMap = new HashMap<>();
                    newWorMap.put("isEnd", "0");     //不是最后一个
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }

                if (i == key.length() - 1) {
                    nowMap.put("isEnd", "1");    //最后一个
                }
            }
        }
    }

    /**
     * 读取敏感词库中的内容,将内容添加到set集合中
     *
     * @throws FileNotFoundException,NullPointerException 抛出空指针或者文件未找到异常
     * @author chenming
     * @since 2014年4月20日 下午2:31:18
     */
    private Set<String> readSensitiveWordFile(String filePath) throws Exception {
        Set<String> set;
        InputStream inputStream;
        try {
            inputStream = new FileInputStream(filePath);
        } catch (FileNotFoundException e) {
            inputStream = Objects.requireNonNull(ClassLoader.getSystemResourceAsStream("sensitive.txt"));
        }
        try (InputStreamReader read = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
            set = new HashSet<>();
            BufferedReader bufferedReader = new BufferedReader(read);
            String txt;
            while ((txt = bufferedReader.readLine()) != null) {    //读取文件,将文件内容放入到set中
                set.add(txt);
            }
        }
        //关闭文件流
        return set;
    }
}

这里注意,首先我们会去找配置文件中配置的sensitive.path

image-20210808003727126
image-20210808003727126

找不到则加载resources下的sensitive.txt

image-20210808003800965
image-20210808003800965

然后是过滤器中需要的过滤请求的封装好的request

代码语言:javascript
复制
package com.ruben.simplescaffold.filter.wrappers;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ruben.simplescaffold.utils.sensitive.SensitiveWordUtils;

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.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 封装请求
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/8/7 21:50
 */
public class RequestWrapper extends HttpServletRequestWrapper {

    private final Map<String, String[]> parameterMap;
    private final byte[] body;

    public RequestWrapper(HttpServletRequest request, SensitiveWordUtils sensitiveWordUtils, Map<String, String[]> parameterMap, String bodyString) {
        super(request);
        if (sensitiveWordUtils == null) {
            this.parameterMap = Optional.ofNullable(parameterMap).orElseGet(super::getParameterMap);
            queryStringPutParameterMap(super.getQueryString());
            this.body = Optional.ofNullable(bodyString).orElseGet(() -> BodyHelper.getBodyString(request)).getBytes(StandardCharsets.UTF_8);
        } else {
            String paramString = JSON.toJSONString(Optional.ofNullable(parameterMap).orElseGet(super::getParameterMap));
            paramString = sensitiveWordUtils.replaceSensitiveWord(paramString, SensitiveWordUtils.MAX_MATCH_TYPE, SensitiveWordUtils.REPLACE_CHAR);
            this.parameterMap = JSON.parseObject(paramString, new TypeReference<Map<String, String[]>>() {
            });
            Optional.ofNullable(super.getQueryString()).ifPresent(queryString -> queryStringPutParameterMap(sensitiveWordUtils.replaceSensitiveWord(queryString, SensitiveWordUtils.MAX_MATCH_TYPE, SensitiveWordUtils.REPLACE_CHAR)));
            this.body = sensitiveWordUtils.replaceSensitiveWord(Optional.ofNullable(bodyString).orElseGet(() -> BodyHelper.getBodyString(request)), SensitiveWordUtils.MAX_MATCH_TYPE, SensitiveWordUtils.REPLACE_CHAR).getBytes(StandardCharsets.UTF_8);
        }

    }

    @Override
    public String getParameter(String name) {
        String[] values = parameterMap.get(name);
        if (Objects.isNull(values) || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        if (parameterMap == null) {
            return super.getParameterMap();
        }
        return parameterMap;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        if (parameterMap == null) {
            return super.getParameterNames();
        }
        return new Vector<>(parameterMap.keySet()).elements();
    }

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

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

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener arg0) {
            }
        };
    }

    @Override
    public String getHeader(String name) {
        return super.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        return super.getHeaderNames();
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        return super.getHeaders(name);
    }

    private void queryStringPutParameterMap(String queryString) {
        if (queryString != null && queryString.trim().length() > 0) {
            String[] params = queryString.split("&");
            for (String param : params) {
                int splitIndex = param.indexOf("=");
                if (splitIndex == -1) {
                    continue;
                }
                String key = param.substring(0, splitIndex);
                if (!this.parameterMap.containsKey(key)) {
                    if (splitIndex < param.length()) {
                        String value = param.substring(splitIndex + 1);
                        this.parameterMap.put(key, new String[]{value});
                    }
                }
            }
        }
    }


    public static class BodyHelper {
        /**
         * 获取请求Body
         *
         * @param request
         * @return
         */
        public static String getBodyString(ServletRequest request) {
            StringBuilder sb = new StringBuilder();
            InputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = request.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return sb.toString();
        }
    }
}

还有个获取响应结果的封装好的response,虽然此处我们没用到,但如果我们要获取filter中的响应体执行过滤,也可以用这个

代码语言:javascript
复制
package com.ruben.simplescaffold.filter.wrappers;

import lombok.SneakyThrows;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

/**
 * 过滤器获取响应结果
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/7/29 10:13
 */
public class ResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream buffer = null;
    private ServletOutputStream outputStream = null;
    private PrintWriter writer = null;

    /**
     * Constructs a response adaptor wrapping the given response.
     *
     * @param response The response to be wrapped
     * @throws IllegalArgumentException if the response is null
     */
    @SneakyThrows
    public ResponseWrapper(HttpServletResponse response) {
        super(response);
        buffer = new ByteArrayOutputStream();
        outputStream = new WrapperOutputStream(buffer);
        writer = new PrintWriter(new OutputStreamWriter(buffer, StandardCharsets.UTF_8));
    }

    /**
     * The default behavior of this method is to return getOutputStream() on the
     * wrapped response object.
     */
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return outputStream;
    }

    /**
     * The default behavior of this method is to return getWriter() on the
     * wrapped response object.
     */
    @Override
    public PrintWriter getWriter() throws IOException {
        return writer;
    }

    /**
     * The default behavior of this method is to call flushBuffer() on the
     * wrapped response object.
     */
    @Override
    @SneakyThrows
    public void flushBuffer() {
        if (outputStream != null) {
            outputStream.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }

    /**
     * The default behavior of this method is to call reset() on the wrapped
     * response object.
     */
    @Override
    public void reset() {
        buffer.reset();
    }

    /**
     * Get response content
     *
     * @param charset HttpServletResponse#getCharacterEncoding()
     * @return response content
     */
    @SneakyThrows
    public String getResponseData(String charset) {
        // 将out、writer中的数据强制输出到WrapperResponse的buffer里面,否则取不到数据
        flushBuffer();
        return buffer.toString(StandardCharsets.UTF_8.displayName());
    }

    /**
     * 内部类,对ServletOutputStream进行包装,指定输出流的输出端
     */
    private static class WrapperOutputStream extends ServletOutputStream {

        private ByteArrayOutputStream bos = null;

        public WrapperOutputStream(ByteArrayOutputStream stream) throws IOException {
            bos = stream;
        }


        /**
         * Writes the specified byte to this output stream. The general
         * contract for <code>write</code> is that one byte is written
         * to the output stream. The byte to be written is the eight
         * low-order bits of the argument <code>b</code>. The 24
         * high-order bits of <code>b</code> are ignored.
         * <p>
         * Subclasses of <code>OutputStream</code> must provide an
         * implementation for this method.
         *
         * @param b the <code>byte</code>.
         * @throws IOException if an I/O error occurs. In particular,
         *                     an <code>IOException</code> may be thrown if the
         *                     output stream has been closed.
         */
        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }


        /**
         * Checks if a non-blocking write will succeed. If this returns
         * <code>false</code>, it will cause a callback to
         * {@link WriteListener#onWritePossible()} when the buffer has emptied. If
         * this method returns <code>false</code> no further data must be written
         * until the contain calls {@link WriteListener#onWritePossible()}.
         *
         * @return <code>true</code> if data can be written, else <code>false</code>
         * @since Servlet 3.1
         */
        @Override
        public boolean isReady() {
            return false;
        }

        /**
         * Sets the {@link WriteListener} for this {@link ServletOutputStream} and
         * thereby switches to non-blocking IO. It is only valid to switch to
         * non-blocking IO within async processing or HTTP upgrade processing.
         *
         * @param listener The non-blocking IO write listener
         * @throws IllegalStateException If this method is called if neither
         *                               async nor HTTP upgrade is in progress or
         *                               if the {@link WriteListener} has already
         *                               been set
         * @throws NullPointerException  If listener is null
         * @since Servlet 3.1
         */
        @Override
        public void setWriteListener(WriteListener listener) {

        }
    }

}

最后是测试用的controller

代码语言:javascript
复制
package com.ruben.simplescaffold.controller.rest;

import com.ruben.simplescaffold.pojo.common.Result;
import com.ruben.simplescaffold.pojo.dto.CommonDTO;
import org.springframework.web.bind.annotation.*;

/**
 * 测试控制层
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/8/7 22:58
 */
@RestController
@RequestMapping("test")
public class TestController {

    @PostMapping
    public Result testBody(@RequestBody CommonDTO commonDTO) {
        return Result.ok().data(commonDTO);
    }

    @GetMapping
    public Result testQueryParam(CommonDTO commonDTO) {
        return Result.ok().data(commonDTO);
    }

    @GetMapping("{path}")
    public Result testPath(@PathVariable String path) {
        return Result.ok().data(path);
    }

}

这里还用到两个类,一个响应结果Result,一个CommonDTOCommonDTO大伙可以使用Map<String,Object>代替下

代码语言:javascript
复制
package com.ruben.simplescaffold.pojo.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.http.HttpStatus;

import java.util.HashMap;
import java.util.Optional;

/**
 * 自定义返回响应
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/6/23 10:40
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(fluent = true)
@EqualsAndHashCode(callSuper = true)
public class Result extends HashMap<String, Object> {
    public static final String DATA_KEY = "data";
    private static final long serialVersionUID = 8639693790921600208L;
    /**
     * 成功状态
     */
    private Boolean success;
    /**
     * 消息
     */
    private String msg;
    /**
     * 状态码
     */
    private Integer code;

    public static Result ok() {
        return httpStatus(HttpStatus.OK);
    }

    public static Result error(String msg) {
        return httpStatus(HttpStatus.INTERNAL_SERVER_ERROR).msg(msg);
    }

    public static Result paramError() {
        return httpStatus(HttpStatus.BAD_REQUEST);
    }

    public static Result notLogin() {
        return httpStatus(HttpStatus.UNAUTHORIZED);
    }

    public static Result httpStatus(HttpStatus httpStatus) {
        httpStatus = Optional.ofNullable(httpStatus).orElse(HttpStatus.OK);
        HttpStatus.Series series = httpStatus.series();
        return new Result().success(httpStatus.is2xxSuccessful()).msg(series.name()).code(HttpStatus.OK.value());
    }

    /**
     * 放入key和value
     *
     * @param key   键
     * @param value 值
     * @return com.kuang.honghaisyweb.pojo.common.Result
     * @author <achao1441470436@gmail.com>
     * @since 2021/6/23 17:07
     */
    @Override
    public Result put(String key, Object value) {
        super.put(key, value);
        return this;
    }

    /**
     * 返回数据
     *
     * @param value 数据
     * @return com.kuang.honghaisyweb.pojo.common.Result
     * @author <achao1441470436@gmail.com>
     * @since 2021/6/23 17:07
     */
    public Result data(Object value) {
        this.put(DATA_KEY, value);
        return this;
    }

}

最后是屏蔽词文本

代码语言:javascript
复制
屏蔽词1号
屏蔽词2号
屏蔽词3号

以及测试案例:

image-20210808005622525
image-20210808005622525
image-20210808005634211
image-20210808005634211
image-20210808005641787
image-20210808005641787

可以看到bodyparam传参都替换成了*号,urlpath传参也替换成了0

完整源码:https://gitee.com/VampireAchao/simple-scaffold.git

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档