黑发不知勤学早,白首方恨读书迟。 ——颜真卿
我们可能想使用本地配置词库、过滤器的方式去做全局屏蔽词处理
这里针对三种参数情况
1.requestParam
传参:http://localhost:8080/test?keywords=屏蔽词2号
2.requestBody
传参:请求体内传json
格式的数据,请求头的Content-Type
为application/json
3.pathvariable
传参:http://localhost:8080/test/屏蔽词3号
这三种应该概括了绝大多数情况下参数传递与接收
代码如下:
首先是过滤器
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");
}
}
中间穿插了几个类:
第一个是屏蔽词过滤处理的工具类
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 匹配规则 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;
}
}
这个工具类需要初始化加载词库,因此我们还有一个初始化的类
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
找不到则加载resources
下的sensitive.txt
然后是过滤器中需要的过滤请求的封装好的request
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
中的响应体执行过滤,也可以用这个
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
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
,一个CommonDTO
,CommonDTO
大伙可以使用Map<String,Object>
代替下
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;
}
}
最后是屏蔽词文本
屏蔽词1号
屏蔽词2号
屏蔽词3号
以及测试案例:
可以看到body
和param
传参都替换成了*
号,url
的path
传参也替换成了0