JAVA-深入浅出过滤器(2.过滤器能做什么)

1.过滤器的应用场景

自定义过滤器实现filter接口,注册到WEB容器即可。既然是实现接口,那么我们就可以实现多个过滤器并用order来定义执行顺序。下面依次为大家展示下面几个应用场景的部分示例代码。
1.自动登录
2.统一设置编码格式
3.访问权限控制
4.敏感字符过滤等
1.1 自动登录
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        //1.获取session中用户对象
        Operator user = (Operator) req.getSession().getAttribute("USER");

        //2.获取当前地址
        String requestURI = req.getRequestURI();

        //会话为空,并且访问地址不为登录页
        if(user == null && !("login").equals(requestURI)){

            //3.查看本地cookie里有没有用户对象
            Cookie autologin = getCookieByName(req.getCookies(), "AUTOLOGIN");
            //存在即重新登录
            if(autologin!= null){
                String value = autologin.getValue();
                UserService service = new UserServiceImpl();
                user = service.login(value);
                req.setAttribute("USER",user);
            }

        }

        //放行
        chain.doFilter(req,resp);


    }
1.2.设置统一编码格式
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //统一设置字符编码格式
        request.setCharacterEncoding("utf-8");
        chain.doFilter(request,response);
    }
1.3. 参数去重
参数格式常见的分为表单参数和JSON格式参数,针对这两种参数格式进行去重
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        ServletRequest requestWrapper = null;

        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String methodType = httpRequest.getMethod();
            //遇到post方法JSON传参才对request进行包装
            if ("POST".equals(methodType) && ContentType.APPLICATION_JSON.getMimeType().equals(request.getContentType())) {
                requestWrapper = new RequestPostJsonWrapper(
                        (HttpServletRequest) request);
            //表单提交方式进行去重
            }else if(ContentType.MULTIPART_FORM_DATA.getMimeType().equals(request.getContentType())){
                requestWrapper = new RequestParamWrapper((HttpServletRequest) request);
            }
        }
        if (null == requestWrapper) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }

    }
这里用到了继承HttpServletRequestWrapper装饰器类,对我们的请求对象进行改装
1.3.1 RequestParamWrapper 表单参数处理
    private Map<String, String[]> params = new HashMap<>();//保存处理后的参数

    public RequestParamWrapper(HttpServletRequest request) throws IOException {
        super(request);
        this.params.putAll(request.getParameterMap());
        this.trimParamValues(); //自定义方法,用于参数去重
    }

    private void trimParamValues(){
        Set<Map.Entry<String,String[]>> entrys = params.entrySet();
        for(Map.Entry<String,String[]> entry :entrys) {
            String[] values=entry.getValue();
            for(int i=0;i<values.length;i++) {
                values[i] = values[i].trim();
            }
            this.params.put(entry.getKey(), values);
        }
    }

    @Override
    public Enumeration<String> getParameterNames() {//重写getParameterNames()
        return new Vector<String>(params.keySet()).elements();
    }


    @Override
    public String getParameter(String name) {//重写getParameter()
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {//重写getParameterValues()
        return params.get(name);
    }

    @Override
    public Map<String,String[]> getParameterMap(){ //重写getParameterMap()
        return this.params;
    }
1.3.2 RequestPostJsonWrapper JSON参数处理,因为JSON参数通过nputStream只能读取一次,会导致action层拿不到参数对象,所以要返回一个新的InputStream对象。
    private final byte[] body;
    private String bodyStr;

    public RequestPostJsonWrapper(HttpServletRequest request) throws IOException {
        super(request);
        String bodyString = getBodyString(request);
        bodyString = trimJsonStr(bodyString);
        body = bodyString.getBytes(Charset.forName("UTF-8"));
        bodyStr=bodyString;
    }

    public String getBodyStr() {
        return bodyStr;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

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

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

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


    public  String getBodyString(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(
                    new InputStreamReader(inputStream, Charset.forName("UTF-8")));

            char[] bodyCharBuffer = new char[1024];
            int len = 0;
            while ((len = reader.read(bodyCharBuffer)) != -1) {
                sb.append(new String(bodyCharBuffer, 0, len));
            }
        } 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();
    }

    /**
     * 去除参数中的空格
     */
    private String trimJsonStr(String bodyString){
        JSONObject jsonObject = JSONObject.parseObject(bodyString);
        Set<String> strings = jsonObject.keySet();
        strings.stream().forEach(key->{
            String value = jsonObject.getString(key);
            if(value != ""){
                jsonObject.put(key,value.trim());
            }
        });

        return jsonObject.toJSONString();
    }

2. 结语

过滤器在我们的开发过程中起到了不可忽视的作用,在我们的许多优秀的框架中都运用到了它。所以熟练的掌握这项技术是必不可少的,那么与过滤器比较相近的就是拦截器,下一篇我们来了解拦截器吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值