SpringBoot利用filter修改response中的返回值

  1. 继承HttpServletResponseWrapper 重新覆盖Response对象,用来获取response中的返回值
package com.example.demo.wrapper;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
 
public class ResponseWrapper extends HttpServletResponseWrapper {
    private ByteArrayOutputStream buffer = null;
    private ServletOutputStream out = null;
    private PrintWriter writer = null;
 
    public ResponseWrapper(HttpServletResponse resp) throws IOException {
        super(resp);
        buffer = new ByteArrayOutputStream();// 真正存储数据的流
        out = new WapperedOutputStream(buffer);
        writer = new PrintWriter(new OutputStreamWriter(buffer));
    }
 
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return out;
    }
 
    @Override
    public PrintWriter getWriter() throws UnsupportedEncodingException {
        return writer;
    }
 
    @Override
    public void flushBuffer() throws IOException {
        if (out != null) {
            out.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }
 
    @Override
    public void reset() {
        buffer.reset();
    }
 
    public byte[] getResponseData() throws IOException {
        flushBuffer();
        return buffer.toByteArray();
    }
 
    public String getContent() throws IOException {
        flushBuffer();
        return buffer.toString();
    }
 
 
    private class WapperedOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream bos = null;
 
        public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
            bos = stream;
        }
 
        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }
 
        @Override
        public void write(byte[] b) throws IOException {
            bos.write(b, 0, b.length);
        }
 
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            bos.write(b, off, len);
        }
 
        @Override
        public boolean isReady() {
            return false;
        }
 
        @Override
        public void setWriteListener(WriteListener writeListener) {
 
        }
    }
}
 

2、创建过滤器,修改response中的内容,返回

package com.example.demo.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * created with IntelliJ IDEA.
 * description: urlPatterns 是需要过滤路径,可以urlPatterns = {"/aaa","/bbb"} 配置ip或域名后的请求地址,可以具体到对应接口,只针对某个接口过滤,也可以/*针对所有
 */
@WebFilter(filterName = "myFilter", urlPatterns = "/*")
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) servletResponse);
        filterChain.doFilter(servletRequest, responseWrapper);
        String contentType = responseWrapper.getContentType();
        byte[] content = responseWrapper.getResponseData();
        String str="";
        if (StringUtils.isNotBlank(contentType) && (contentType.contains(MediaType.APPLICATION_JSON_VALUE) || contentType.contains(MediaType.TEXT_HTML_VALUE))) {
           str = new String(content);
            str=str+"xiaoming";
            System.out.println("filter:"+str);
            HttpServletResponse response=(HttpServletResponse)servletResponse;
            writeResponse(response,200,str);
        }
    }
    
   public static void writeResponse(HttpServletResponse response, int status, String json) {
        try {
            response.reset();//很重要
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "*");
            response.setContentType("application/json;charset=UTF-8");
            response.setStatus(status);
            response.getWriter().write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void destroy() {
        System.out.println("destroy...");
    }
}

3、可以代码配置过滤器,也可以注解式配置

(1)代码配置

package com.example.demo.config;
 
import com.example.demo.filter.ResponseFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
 
import java.util.ArrayList;
import java.util.List;
 
@SpringBootConfiguration
public class FilterConfig {
    @Autowired
   private ResponseFilter  responseFilter;
    @Bean
    public FilterRegistrationBean getFilterConfig(){
        FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();
        filterRegistrationBean.setFilter(responseFilter);
        List<String> filterList=new ArrayList<>();
        filterList.add("/*");
        filterRegistrationBean.setUrlPatterns(filterList);
        return filterRegistrationBean;
    }
 
 
}

(2)注解配置 在Application 启动类 添加 ​​@ServletComponentScan​​ 注解
注:MyFilter 一定要在 ​​@ServletComponentScan​​ 的扫描范围内

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

延展可以针对filter过滤路径下的返回值修改,比如敏感词操作:
4、在MyFilter内的doFilter 获取到 str 即 返回值内容后可以将其传递到敏感词的工具类下,进行敏感词替换。
注意:contentType 是 MediaType.TEXT_HTML_VALUE 类型则不要转换 json转换报错,如要剔除

package com.util;


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 敏感词处理 - DFA算法实现
 *
 * @author jeff
 * @since 2018/3/15
 */
public class SensitiveWordUtil {

    /**
     * 敏感词匹配规则
     */
    public static final int MinMatchTYpe = 1;      //最小匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国]人
    public static final int MaxMatchType = 2;      //最大匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国人]

    /**
     * 敏感词集合
     */
    public static HashMap sensitiveWordMap;

    /**
     * 初始化敏感词库,构建DFA算法模型
     *
     * @param sensitiveWordSet 敏感词库
     */
    public static synchronized void init(Set<String> sensitiveWordSet) {
        initSensitiveWordMap(sensitiveWordSet);
    }

    /**
     * 初始化敏感词库,构建DFA算法模型
     *
     * @param sensitiveWordSet 敏感词库
     */
    private static void initSensitiveWordMap(Set<String> sensitiveWordSet) {
        //初始化敏感词容器,减少扩容操作
        sensitiveWordMap = new HashMap(sensitiveWordSet.size());
        String key;
        Map nowMap;
        Map<String, String> newWorMap;
        //迭代sensitiveWordSet
        Iterator<String> iterator = sensitiveWordSet.iterator();
        while (iterator.hasNext()) {
            //关键字
            key = iterator.next();
            nowMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++) {
                //转换成char型
                char keyChar = key.charAt(i);
                //库中获取关键字
                Object wordMap = nowMap.get(keyChar);
                //如果存在该key,直接赋值,用于下一个循环获取
                if (wordMap != null) {
                    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");
                }
            }
        }
    }

    /**
     * 判断文字是否包含敏感字符
     *
     * @param txt       文字
     * @param matchType 匹配规则 1:最小匹配规则,2:最大匹配规则
     * @return 若包含返回true,否则返回false
     */
    public static boolean contains(String txt, int matchType) {
        boolean flag = false;
        for (int i = 0; i < txt.length(); i++) {
            int matchFlag = checkSensitiveWord(txt, i, matchType); //判断是否包含敏感字符
            if (matchFlag > 0) {    //大于0存在,返回true
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 判断文字是否包含敏感字符
     *
     * @param txt 文字
     * @return 若包含返回true,否则返回false
     */
    public static boolean contains(String txt) {
        return contains(txt, MaxMatchType);
    }

    /**
     * 获取文字中的敏感词
     *
     * @param txt       文字
     * @param matchType 匹配规则 1:最小匹配规则,2:最大匹配规则
     * @return
     */
    public static 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 文字
     * @return
     */
    public static Set<String> getSensitiveWord(String txt) {
        return getSensitiveWord(txt, MaxMatchType);
    }

    /**
     * 替换敏感字字符
     *
     * @param txt         文本
     * @param replaceChar 替换的字符,匹配的敏感词以字符逐个替换,如 语句:我爱中国人 敏感词:中国人,替换字符:*, 替换结果:我爱***
     * @param matchType   敏感词匹配规则
     * @return
     */
    public static String replaceSensitiveWord(String txt, char replaceChar, int matchType) {
        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 txt         文本
     * @param replaceChar 替换的字符,匹配的敏感词以字符逐个替换,如 语句:我爱中国人 敏感词:中国人,替换字符:*, 替换结果:我爱***
     * @return
     */
    public static String replaceSensitiveWord(String txt, char replaceChar) {
        return replaceSensitiveWord(txt, replaceChar, MaxMatchType);
    }

    /**
     * 替换敏感字字符
     *
     * @param txt        文本
     * @param replaceStr 替换的字符串,匹配的敏感词以字符逐个替换,如 语句:我爱中国人 敏感词:中国人,替换字符串:[屏蔽],替换结果:我爱[屏蔽]
     * @param matchType  敏感词匹配规则
     * @return
     */
    public static String replaceSensitiveWord(String txt, String replaceStr, int matchType) {
        String resultTxt = txt;
        //获取所有的敏感词
        Set<String> set = getSensitiveWord(txt, matchType);
        Iterator<String> iterator = set.iterator();
        String word;
        while (iterator.hasNext()) {
            word = iterator.next();
            resultTxt = resultTxt.replaceAll(word, replaceStr);
        }

        return resultTxt;
    }

    /**
     * 替换敏感字字符
     *
     * @param txt        文本
     * @param replaceStr 替换的字符串,匹配的敏感词以字符逐个替换,如 语句:我爱中国人 敏感词:中国人,替换字符串:[屏蔽],替换结果:我爱[屏蔽]
     * @return
     */
    public static String replaceSensitiveWord(String txt, String replaceStr) {
        return replaceSensitiveWord(txt, replaceStr, MaxMatchType);
    }

    /**
     * 获取替换字符串
     *
     * @param replaceChar
     * @param length
     * @return
     */
    private static String getReplaceChars(char replaceChar, int length) {
        String resultReplace = String.valueOf(replaceChar);
        for (int i = 1; i < length; i++) {
            resultReplace += replaceChar;
        }

        return resultReplace;
    }

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

    /**
     * 检测敏感词
     * @param text 需要检测的内容
     * @param path 敏感词字典路径
     */
    public static boolean wordFilter(String text,String path){
        HashSet<String> sensitiveWordSet = getTxt(path);
        String str = del(text);
        if(sensitiveWordSet==null){
            System.out.println("error");
        }else {
            //初始化敏感词库
            SensitiveWordUtil.init(sensitiveWordSet);
            //是否含有关键字
            boolean result = SensitiveWordUtil.contains(str);
            result = SensitiveWordUtil.contains(str, SensitiveWordUtil.MaxMatchType);
            return result;
        }
        return true;
    }


//    public static void main(String[] args) {
//        HashSet<String> sensitiveWordSet = getTxt("");
//        if(sensitiveWordSet==null){
//            System.out.println("error");
//        }else {
//        //初始化敏感词库
//        SensitiveWordUtil.init(sensitiveWordSet);
//        System.out.println("敏感词的数量:" + SensitiveWordUtil.sensitiveWordMap.size());
//        String string = "靖国神社";
//        System.out.println("待检测语句字数:" + string.length());
//        //是否含有关键字
//        boolean result = SensitiveWordUtil.contains(string);
//        result = SensitiveWordUtil.contains(string, SensitiveWordUtil.MaxMatchType);
//        System.out.println(result);
//
//        //获取语句中的敏感词
        Set<String> set = SensitiveWordUtil.getSensitiveWord(string);
        System.out.println("语句中包含敏感词的个数为:" + set.size() + "。包含:" + set);
        set = SensitiveWordUtil.getSensitiveWord(string, SensitiveWordUtil.MaxMatchType);
        System.out.println("语句中包含敏感词的个数为:" + set.size() + "。包含:" + set);
//
//        //替换语句中的敏感词
        String filterStr = SensitiveWordUtil.replaceSensitiveWord(string, '*');
        System.out.println(filterStr);
        filterStr = SensitiveWordUtil.replaceSensitiveWord(string, '*', SensitiveWordUtil.MaxMatchType);
        System.out.println(filterStr);

        String filterStr2 = SensitiveWordUtil.replaceSensitiveWord(string, "[*敏感词*]");
        System.out.println(filterStr2);
        filterStr2 = SensitiveWordUtil.replaceSensitiveWord(string, "[*敏感词*]", SensitiveWordUtil.MaxMatchType);
        System.out.println(filterStr2);
//        }
//
//    }


    /**
     * 获取txt字典敏感词库
     * @return
     */
        public static   HashSet<String> getTxt(String readerPath) {
            //创建字符缓冲输入流对象
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(readerPath));
                //创建ArrayList集合对象
                HashSet<String> array = new HashSet<>();
                //调用字符缓冲输入流对象的方法读数据
                String line;
                while ((line=br.readLine())!=null) {
                    //把读取到的字符串数据存储到集合中
                    array.add(line);
                }
                //释放资源
                br.close();
                return array;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
                return null;
        }
    /**
     * 去除字符串中的空格以及特殊字符
     */
    private static String del(String str){
        str = str.replaceAll(" ", "");//去除空格
        Pattern p = Pattern.compile("[`~☆★!@#$%^&*()+=|{}':;,\\[\\]》·.<>/?~!@#¥%……()——+|{}【】‘;:”“’。,、?]");//去除特殊字符
        Matcher m = p.matcher(str);
        str = m.replaceAll("").trim().replace(" ", "").replace("\\", "");//将匹配的特殊字符转变为空
        return str;
    }
}

5、在初始化的时候springboot可以采用@postConstruct初始化 这样就可以在类下添加方法调用敏感词工具类下的初始化方法,进行敏感词初始化,剩下的就是需要在哪里做敏感词就可以在webFilter添加路径,或者自己手动调用敏感词工具类。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Spring Boot配置Filter有两种方式: 1. 实现javax.servlet.Filter接口,使用注解@WebFilter,然后在Spring Boot的配置类添加ServletRegistrationBean将Filter注册到Servlet容器。 例如: ```java @WebFilter(urlPatterns = "/api/*") public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化操作 } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 过滤操作 } @Override public void destroy() { // 销毁操作 } } @Configuration public class WebConfig { @Bean public ServletRegistrationBean<MyFilter> myFilter() { ServletRegistrationBean<MyFilter> registrationBean = new ServletRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/api/*"); registrationBean.setName("MyFilter"); registrationBean.setOrder(1); return registrationBean; } } ``` 2. 使用@Configuration注解的类,实现FilterRegistrationBean,将Filter注册到Servlet容器。 例如: ```java @Configuration public class WebConfig { @Bean public FilterRegistrationBean<MyFilter> myFilter() { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/api/*"); registrationBean.setName("MyFilter"); registrationBean.setOrder(1); return registrationBean; } } ``` 上述两种方式都可以用来配置Filter,具体选哪种方式,可以根据实际情况进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yangyang_VV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值