过滤器应用【编码、敏感词、压缩、转义过滤器】(修订版)

字符过滤器 jsp 中的字符过滤器,屏蔽网页中或JFreeChart中的乱码问题 立即下载

前言

只有光头才能变强。

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y


在上篇博文中,我们已经讲解了过滤器的基本概念,使用以及简单的Servlet应用了。这篇博文主要讲解过滤器的高级应用。。

编码过滤器

目的:解决全站的乱码问题

开发过滤器

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {    //将request和response强转成http协议的    HttpServletRequest httpServletRequest = (HttpServletRequest) req;    HttpServletResponse httpServletResponse = (HttpServletResponse) resp;    httpServletRequest.setCharacterEncoding("UTF-8");    httpServletResponse.setCharacterEncoding("UTF-8");    httpServletResponse.setContentType("text/html;charset=UTF-8");    chain.doFilter(httpServletRequest, httpServletResponse);}

    //将request和response强转成http协议的
    HttpServletRequest httpServletRequest = (HttpServletRequest) req;
    HttpServletResponse httpServletResponse = (HttpServletResponse) resp;

    httpServletRequest.setCharacterEncoding("UTF-8");
    httpServletResponse.setCharacterEncoding("UTF-8");
    httpServletResponse.setContentType("text/html;charset=UTF-8");

    chain.doFilter(httpServletRequest, httpServletResponse);
}

第一次测试

Servlet1中向浏览器回应中文数据,没有出现乱码。

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    response.getWriter().write("看完博客点赞!");}

    response.getWriter().write("看完博客点赞!");

}
640?wx_fmt=png
这里写图片描述

分析

上面的过滤器是不完善的,因为浏览器用get方式提交给服务器的中文数据,单单靠上面的过滤器是无法完成的!

那么我们需要怎么做呢??我们之前解决get方式的乱码问题是这样的:使用request获取传递过来的数据,经过ISO 8859-1反编码获取得到不是乱码的数据(传到Servlet上的数据已经被ISO 8859-1编码过了,反编码就可以获取原来的数据),再用UTF-8编码,得到中文数据!

在Servlet获取浏览器以GET方式提交过来的中文是乱码的根本原因是:getParameter()方法是以ISO 8859-1的编码来获取浏览器传递过来的数据的,得到的是乱码

既然知道了根本原因,那也好办了:过滤器传递的request对象,使用getParameter()方法的时候,获取得到的是正常的中文数据

也就是说,sun公司为我们提供的request对象是不够用的,因为sun公司提供的request对象使用getParameter()获取get方式提交过来的数据是乱码,于是我们要增强request对象(使得getParameter()获取得到的是中文)!

增强request对象

增强request对象,我们要使用包装设计模式!

包装设计模式的五个步骤:

sun公司也知道我们可能对request对象的方法不满意,于是提供了HttpServletRequestWrapper类给我们实现(如果实现HttpServletRequest接口的话,要实现太多的方法了!)

class MyRequest extends HttpServletRequestWrapper {    private HttpServletRequest request;    public MyRequest(HttpServletRequest request) {        super(request);        this.request = request;    }    @Override    public String getParameter(String name) {        String value = this.request.getParameter(name);        if (value == null) {            return null;        }        //如果不是get方法的,直接返回就行了        if (!this.request.getMethod().equalsIgnoreCase("get")) {            return null;        }        try {            //进来了就说明是get方法,把乱码的数据            value = new String(value.getBytes("ISO8859-1"), this.request.getCharacterEncoding());            return value ;        } catch (UnsupportedEncodingException e) {            e.printStackTrace();            throw new RuntimeException("不支持该编码");        }    }}

    private HttpServletRequest request;

    public MyRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    @Override
    public String getParameter(String name) {
        String value = this.request.getParameter(name);

        if (value == null) {
            return null;
        }

        //如果不是get方法的,直接返回就行了
        if (!this.request.getMethod().equalsIgnoreCase("get")) {
            return null;
        }

        try {

            //进来了就说明是get方法,把乱码的数据
            value = new String(value.getBytes("ISO8859-1"), this.request.getCharacterEncoding());
            return value ;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();

            throw new RuntimeException("不支持该编码");
        }

    }
}

将被增强的request对象传递给目标资源,那么目标资源使用request调用getParameter()方法的时候,获取得到的就是中文数据,而不是乱码了!

//将request和response强转成http协议的HttpServletRequest httpServletRequest = (HttpServletRequest) req;HttpServletResponse httpServletResponse = (HttpServletResponse) resp;httpServletRequest.setCharacterEncoding("UTF-8");httpServletResponse.setCharacterEncoding("UTF-8");httpServletResponse.setContentType("text/html;charset=UTF-8");MyRequest myRequest = new MyRequest(httpServletRequest);//传递给目标资源的request是被增强后的。chain.doFilter(myRequest, httpServletResponse);
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
HttpServletResponse httpServletResponse = (HttpServletResponse) resp;

httpServletRequest.setCharacterEncoding("UTF-8");
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");

MyRequest myRequest = new MyRequest(httpServletRequest);

//传递给目标资源的request是被增强后的。
chain.doFilter(myRequest, httpServletResponse);

第二次测试

<form action="${pageContext.request.contextPath}/Servlet1" method="get">    <input type="hidden" name="username" value="中国">    <input type="submit" value="提交"></form>

    <input type="hidden" name="username" value="中国">


    <input type="submit" value="提交">
</form>
640?wx_fmt=gif
这里写图片描述

敏感词的过滤器

如果用户输入了敏感词(傻b、尼玛、操蛋等等不文明语言时),我们要将这些不文明用于屏蔽掉,替换成符号!

要实现这样的功能也很简单,用户输入的敏感词肯定是在getParameter()获取的,我们在getParameter()得到这些数据的时候,判断有没有敏感词汇,如果有就替换掉就好了!简单来说:也是要增强request对象

增强request对象

class MyDirtyRequest extends HttpServletRequestWrapper {    HttpServletRequest request;    //定义一堆敏感词汇    private List<String> list = Arrays.asList("傻b", "尼玛", "操蛋");    public MyDirtyRequest(HttpServletRequest request) {        super(request);        this.request = request;    }    @Override    public String getParameter(String name) {        String value = this.request.getParameter(name);        if (value == null) {            return null;        }        //遍历list集合,看看获取得到的数据有没有敏感词汇        for (String s : list) {            if (s.equals(value)) {                value = "*****";            }        }        return value ;    }}

    HttpServletRequest request;

    //定义一堆敏感词汇
    private List<String> list = Arrays.asList("傻b", "尼玛", "操蛋");

    public MyDirtyRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    @Override
    public String getParameter(String name) {

        String value = this.request.getParameter(name);

        if (value == null) {
            return null;
        }

        //遍历list集合,看看获取得到的数据有没有敏感词汇
        for (String s : list) {

            if (s.equals(value)) {
                value = "*****";
            }
        }

        return value ;
    }
}

开发过滤器

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {    //将request和response强转成http协议的    HttpServletRequest httpServletRequest = (HttpServletRequest) req;    HttpServletResponse httpServletResponse = (HttpServletResponse) resp;    MyDirtyRequest dirtyRequest = new MyDirtyRequest(httpServletRequest);    //传送给目标资源的是被增强后的request对象    chain.doFilter(dirtyRequest, httpServletResponse);}

    //将request和response强转成http协议的
    HttpServletRequest httpServletRequest = (HttpServletRequest) req;
    HttpServletResponse httpServletResponse = (HttpServletResponse) resp;

    MyDirtyRequest dirtyRequest = new MyDirtyRequest(httpServletRequest);

    //传送给目标资源的是被增强后的request对象
    chain.doFilter(dirtyRequest, httpServletResponse);
}

测试

640?wx_fmt=gif
这里写图片描述

压缩资源过滤器

按照过滤器的执行顺序:执行完目标资源,过滤器后面的代码还会执行。所以,我们在过滤器中可以获取执行完目标资源后的response对象!

我们知道sun公司提供的response对象调用write()方法,是直接把数据返回给浏览器的。我们要想实现压缩的功能,write()方法就不能直接把数据写到浏览器上!

这和上面是类似的,过滤器传递给目标资源的response对象就需要被我们增强,使得目标资源调用writer()方法的时候不把数据直接写到浏览器上!

增强response对象

response对象可能会使用PrintWriter或者ServletOutputStream对象来调用writer()方法的,所以我们增强response对象的时候,需要把getOutputSteam和getWriter()重写

class MyResponse extends HttpServletResponseWrapper{    HttpServletResponse response;    public MyResponse(HttpServletResponse response) {        super(response);        this.response = response;    }    @Override    public ServletOutputStream getOutputStream() throws IOException {        return super.getOutputStream();    }    @Override    public PrintWriter getWriter() throws IOException {        return super.getWriter();    }}

    HttpServletResponse response;
    public MyResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }


    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return super.getOutputStream();
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return super.getWriter();
    }
}

接下来,ServletOutputSteam要调用writer()方法,使得它不会把数据写到浏览器上。这又要我们增强一遍了!

增强ServletOutputSteam

/*增强ServletOutputSteam,让writer方法不把数据直接返回给浏览器*/class MyServletOutputStream extends ServletOutputStream{    private ByteArrayOutputStream byteArrayOutputStream;    public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {        this.byteArrayOutputStream = byteArrayOutputStream;    }    //当调用write()方法的时候,其实是把数据写byteArrayOutputSteam上    @Override    public void write(int b) throws IOException {        this.byteArrayOutputStream.write(b);    }}
class MyServletOutputStream extends ServletOutputStream{

    private ByteArrayOutputStream byteArrayOutputStream;

    public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
        this.byteArrayOutputStream = byteArrayOutputStream;
    }

    //当调用write()方法的时候,其实是把数据写byteArrayOutputSteam上
    @Override
    public void write(int b) throws IOException {
        this.byteArrayOutputStream.write(b);

    }
}

增强PrintWriter

PrintWriter对象就好办了,它本来就是一个包装类,看它的构造方法,我们直接可以把ByteArrayOutputSteam传递给PrintWriter上。

640?wx_fmt=png
这里写图片描述
@Overridepublic PrintWriter getWriter() throws IOException {    printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));    return printWriter;}
public PrintWriter getWriter() throws IOException {
    printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));

    return printWriter;
}

获取缓存数据

我们把数据都写在了ByteArrayOutputSteam上了,应该提供方法给外界过去缓存中的数据!

public byte[] getBuffer() {    try {        //防止数据在缓存中,要刷新一下!        if (printWriter != null) {            printWriter.close();        }        if (byteArrayOutputStream != null) {            byteArrayOutputStream.flush();            return byteArrayOutputStream.toByteArray();        }    } catch (IOException e) {        e.printStackTrace();    }    return null;}byte[] getBuffer() {

    try {

        //防止数据在缓存中,要刷新一下!
        if (printWriter != null) {
            printWriter.close();
        }
        if (byteArrayOutputStream != null) {
            byteArrayOutputStream.flush();
            return byteArrayOutputStream.toByteArray();
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

增强response的完整代码

class MyResponse extends HttpServletResponseWrapper{    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();    private PrintWriter printWriter ;    private HttpServletResponse response;    public MyResponse(HttpServletResponse response) {        super(response);        this.response = response;    }    @Override    public ServletOutputStream getOutputStream() throws IOException {        //这个的ServletOutputSteam对象调用write()方法的时候,把数据是写在byteArrayOutputSteam上的        return new MyServletOutputStream(byteArrayOutputStream);    }    @Override    public PrintWriter getWriter() throws IOException {        printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));        return printWriter;    }    public byte[] getBuffer() {        try {            //防止数据在缓存中,要刷新一下!            if (printWriter != null) {                printWriter.close();            }            if (byteArrayOutputStream != null) {                byteArrayOutputStream.flush();                return byteArrayOutputStream.toByteArray();            }        } catch (IOException e) {            e.printStackTrace();        }        return null;    }}

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    private PrintWriter printWriter ;

    private HttpServletResponse response;
    public MyResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }


    @Override
    public ServletOutputStream getOutputStream() throws IOException {

        //这个的ServletOutputSteam对象调用write()方法的时候,把数据是写在byteArrayOutputSteam上的
        return new MyServletOutputStream(byteArrayOutputStream);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));

        return printWriter;
    }

    public byte[] getBuffer() {

        try {

            //防止数据在缓存中,要刷新一下!
            if (printWriter != null) {
                printWriter.close();
            }
            if (byteArrayOutputStream != null) {
                byteArrayOutputStream.flush();
                return byteArrayOutputStream.toByteArray();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

过滤器

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {    HttpServletRequest request = (HttpServletRequest) req;    HttpServletResponse response = (HttpServletResponse) resp;    MyResponse myResponse = new MyResponse(response);    //把被增强的response对象传递进去,目标资源调用write()方法的时候就不会直接把数据写在浏览器上了    chain.doFilter(request, myResponse);    //得到目标资源想要返回给浏览器的数据    byte[] bytes = myResponse.getBuffer();    //输出原来的大小    System.out.println("压缩前:"+bytes.length);    //使用GZIP来压缩资源,再返回给浏览器    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();    GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);    gzipOutputStream.write(bytes);    //得到压缩后的数据    byte[] gzip = byteArrayOutputStream.toByteArray();    System.out.println("压缩后:" + gzip.length);    //还要设置头,告诉浏览器,这是压缩数据!    response.setHeader("content-encoding", "gzip");    response.setContentLength(gzip.length);    response.getOutputStream().write(gzip);}


    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    MyResponse myResponse = new MyResponse(response);

    //把被增强的response对象传递进去,目标资源调用write()方法的时候就不会直接把数据写在浏览器上了
    chain.doFilter(request, myResponse);

    //得到目标资源想要返回给浏览器的数据
    byte[] bytes = myResponse.getBuffer();

    //输出原来的大小
    System.out.println("压缩前:"+bytes.length);


    //使用GZIP来压缩资源,再返回给浏览器
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
    gzipOutputStream.write(bytes);

    //得到压缩后的数据
    byte[] gzip = byteArrayOutputStream.toByteArray();

    System.out.println("压缩后:" + gzip.length);

    //还要设置头,告诉浏览器,这是压缩数据!
    response.setHeader("content-encoding", "gzip");
    response.setContentLength(gzip.length);
    response.getOutputStream().write(gzip);

}

测试

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    response.getWriter().write("fdshfidsuhfidusfhuidsfhuidshdsuifhsd" +            "uifhsduifffffdshfidsuhfidusfhuidsfhuidshdsuif" +            "hsduifhsduifffffdshfidsuhfidusfhuidsfhuidshd" +            "suifhsduifhsduifffffdshfidsuhfidusfhuidsfhuidsh" +            "dsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuids" +            "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuid" +            "shdsuifhsduifhsduiffdshfidsuhfidusfhuidsfhuids" +            "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhui" +            "dshdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfh" +            "uidshdsuifhsduifhsduifffffdshfidsuhfidusfhuids" +            "fhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhuid" +            "sfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhui" +            "dsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfh" +            "uidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusf" +            "huidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidus" +            "fhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhfid" +            "usfhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhf" +            "idusfhuidsfhuidshdsuifhsduifhsd" +            "uifffffdshfidsuhfidusfhuidsfhuidshdsuifhsduifhsduifffffff");}

    response.getWriter().write("fdshfidsuhfidusfhuidsfhuidshdsuifhsd" +
            "uifhsduifffffdshfidsuhfidusfhuidsfhuidshdsuif" +
            "hsduifhsduifffffdshfidsuhfidusfhuidsfhuidshd" +
            "suifhsduifhsduifffffdshfidsuhfidusfhuidsfhuidsh" +
            "dsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuids" +
            "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhuid" +
            "shdsuifhsduifhsduiffdshfidsuhfidusfhuidsfhuids" +
            "hdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfhui" +
            "dshdsuifhsduifhsduifffffdshfidsuhfidusfhuidsfh" +
            "uidshdsuifhsduifhsduifffffdshfidsuhfidusfhuids" +
            "fhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhuid" +
            "sfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfhui" +
            "dsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusfh" +
            "uidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidusf" +
            "huidsfhuidshdsuifhsduifhsduifffffdshfidsuhfidus" +
            "fhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhfid" +
            "usfhuidsfhuidshdsuifhsduifhsduifffffdshfidsuhf" +
            "idusfhuidsfhuidshdsuifhsduifhsd" +
            "uifffffdshfidsuhfidusfhuidsfhuidshdsuifhsduifhsduifffffff");

}
640?wx_fmt=png
这里写图片描述

HTML转义过滤器

只要把getParameter()获取得到的数据转义一遍,就可以完成功能了。

增强request

class MyHtmlRequest extends HttpServletRequestWrapper{    private HttpServletRequest request;    public MyHtmlRequest(HttpServletRequest request) {        super(request);        this.request = request;    }    @Override    public String getParameter(String name) {        String value = this.request.getParameter(name);        return this.Filter(value);    }    public String Filter(String message) {        if (message == null)            return (null);        char content[] = new char[message.length()];        message.getChars(0, message.length(), content, 0);        StringBuffer result = new StringBuffer(content.length + 50);        for (int i = 0; i < content.length; i++) {            switch (content[i]) {                case '<':                    result.append("&lt;");                    break;                case '>':                    result.append("&gt;");                    break;                case '&':                    result.append("&amp;");                    break;                case '"':                    result.append("&quot;");                    break;                default:                    result.append(content[i]);            }        }        return (result.toString());    }}

    private HttpServletRequest request;

    public MyHtmlRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }


    @Override
    public String getParameter(String name) {

        String value = this.request.getParameter(name);
        return this.Filter(value);

    }

    public String Filter(String message) {
        if (message == null)
            return (null);

        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuffer result = new StringBuffer(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
                case '<':
                    result.append("&lt;");
                    break;
                case '>':
                    result.append("&gt;");
                    break;
                case '&':
                    result.append("&amp;");
                    break;
                case '"':
                    result.append("&quot;");
                    break;
                default:
                    result.append(content[i]);
            }
        }
        return (result.toString());

    }

}

过滤器

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {    HttpServletRequest request = (HttpServletRequest) req;    HttpServletResponse response = (HttpServletResponse) resp;    MyHtmlRequest myHtmlRequest = new MyHtmlRequest(request);    //传入的是被增强的request!    chain.doFilter(myHtmlRequest, response);}



    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    MyHtmlRequest myHtmlRequest = new MyHtmlRequest(request);

    //传入的是被增强的request!
    chain.doFilter(myHtmlRequest, response);

}

测试

jsp代码:

<form action="${pageContext.request.contextPath}/Servlet1" method="post">    <input type="hidden" name="username" value="<h1>你好i好<h1>">    <input type="submit" value="提交"></form>


    <input type="hidden" name="username" value="<h1>你好i好<h1>">

    <input type="submit" value="提交">
</form>

Servlet代码:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    String value = request.getParameter("username");    response.getWriter().write(value);}

    String value = request.getParameter("username");
    response.getWriter().write(value);

}
640?wx_fmt=png
这里写图片描述

缓存数据到内存中

在前面我们已经做过了,让浏览器不缓存数据【验证码的图片是不应该缓存的】。

现在我们要做的是:缓存数据到内存中【如果某个资源重复使用,不轻易变化,应该缓存到内存中】

这个和压缩数据的Filter非常类似的,因为让数据不直接输出给浏览器,把数据用一个容器(ByteArrayOutputSteam)存起来。如果已经有缓存了,就取缓存的。没有缓存就执行目标资源!

增强response对象

class MyResponse extends HttpServletResponseWrapper {    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();    private PrintWriter printWriter ;    private HttpServletResponse response;    public MyResponse(HttpServletResponse response) {        super(response);        this.response = response;    }    @Override    public ServletOutputStream getOutputStream() throws IOException {        //这个的ServletOutputSteam对象调用write()方法的时候,把数据是写在byteArrayOutputSteam上的        return new MyServletOutputStream(byteArrayOutputStream);    }    @Override    public PrintWriter getWriter() throws IOException {        printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));        return printWriter;    }    public byte[] getBuffer() {        try {            //防止数据在缓存中,要刷新一下!            if (printWriter != null) {                printWriter.close();            }            if (byteArrayOutputStream != null) {                byteArrayOutputStream.flush();                return byteArrayOutputStream.toByteArray();            }        } catch (IOException e) {            e.printStackTrace();        }        return null;    }}//增强ServletOutputSteam,让writer方法不把数据直接返回给浏览器class MyServletOutputStream extends ServletOutputStream {    private ByteArrayOutputStream byteArrayOutputStream;    public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {        this.byteArrayOutputStream = byteArrayOutputStream;    }    //当调用write()方法的时候,其实是把数据写byteArrayOutputSteam上    @Override    public void write(int b) throws IOException {        this.byteArrayOutputStream.write(b);    }}

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    private PrintWriter printWriter ;

    private HttpServletResponse response;
    public MyResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }


    @Override
    public ServletOutputStream getOutputStream() throws IOException {

        //这个的ServletOutputSteam对象调用write()方法的时候,把数据是写在byteArrayOutputSteam上的
        return new MyServletOutputStream(byteArrayOutputStream);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, this.response.getCharacterEncoding()));

        return printWriter;
    }

    public byte[] getBuffer() {

        try {

            //防止数据在缓存中,要刷新一下!
            if (printWriter != null) {
                printWriter.close();
            }
            if (byteArrayOutputStream != null) {
                byteArrayOutputStream.flush();
                return byteArrayOutputStream.toByteArray();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}


//增强ServletOutputSteam,让writer方法不把数据直接返回给浏览器

class MyServletOutputStream extends ServletOutputStream {

    private ByteArrayOutputStream byteArrayOutputStream;

    public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
        this.byteArrayOutputStream = byteArrayOutputStream;
    }

    //当调用write()方法的时候,其实是把数据写byteArrayOutputSteam上
    @Override
    public void write(int b) throws IOException {
        this.byteArrayOutputStream.write(b);

    }
}

过滤器

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {    //定义一个Map集合,key为页面的地址,value为内存的缓存    Map<String, byte[]> map = new HashMap<>();    HttpServletRequest request = (HttpServletRequest) req;    HttpServletResponse response = (HttpServletResponse) resp;    //得到客户端想要请求的资源    String uri = request.getRequestURI();    byte[] bytes = map.get(uri);    //如果有缓存,直接返回给浏览器就行了,就不用执行目标资源了    if (bytes != null) {        response.getOutputStream().write(bytes);        return ;    }    //如果没有缓存,就让目标执行    MyResponse myResponse = new MyResponse(response);    chain.doFilter(request, myResponse);    //得到目标资源想要发送给浏览器的数据    byte[] b = myResponse.getBuffer();    //把数据存到集合中    map.put(uri, b);    //把数据返回给浏览器    response.getOutputStream().write(b);}

    //定义一个Map集合,key为页面的地址,value为内存的缓存
    Map<String, byte[]> map = new HashMap<>();

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

    //得到客户端想要请求的资源
    String uri = request.getRequestURI();
    byte[] bytes = map.get(uri);

    //如果有缓存,直接返回给浏览器就行了,就不用执行目标资源了
    if (bytes != null) {
        response.getOutputStream().write(bytes);
        return ;
    }

    //如果没有缓存,就让目标执行
    MyResponse myResponse = new MyResponse(response);
    chain.doFilter(request, myResponse);

    //得到目标资源想要发送给浏览器的数据
    byte[] b = myResponse.getBuffer();

    //把数据存到集合中
    map.put(uri, b);

    //把数据返回给浏览器
    response.getOutputStream().write(b);


}

测试

尽管是刷新,获取得到的也是从缓存拿到的数据!

640?wx_fmt=gif
这里写图片描述

最后

乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!

640?wx_fmt=jpeg

有帮助?好看!转发!640

英伟达NVIDIA数字IC后端笔试真题(ASIC Physical Design Engineer) 英伟达NVIDIA数字IC后端笔试真题(ASIC Physical Design方向) 阅读详情

相关推荐

扫地机器人:从仿真到决策,一个完整SLAM导航系统的自研之路

本文详细记录了从零开始自研扫地机器人SLAM导航系统的全过程,涵盖ROS-Gazebo仿真系统搭建、地图预处理优化、全覆盖规划算法迭代等关键技术。通过三次算法升级,最终实现92%的清洁效率,并分享DWA调参、状态机设计等实战经验,为开发者提供从仿真到落地的完整解决方案。

weixin_29053695的博客 352

过滤器第二篇【高级应用】

前言 在上篇博文中,我们已经讲解了过滤器的基本概念,使用以及简单的Servlet应用了。这篇博文主要讲解过滤器的高级应用。 编码过滤器 目的:解决全站的乱码问题 开发过滤器 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Ser...

3y 458

小样本物体检测

Few-Shot Object Detection with Attention-RPN and Multi-Relation Detector 关键:提出了一个小样本数据集:数据集 步骤: 提取support img为一过滤特征 使用support img的特征来过滤query img,最后将过滤后的特征输入RPN网络中 RPN网络层的输出,会进行多头判断,使用全局信息检测,使用局部信息检测,一对多检测 Attention-Based Region Proposal Network Increme

qq_21157073的博客 5266

我的世界java版进不去服务器_Minecraft-Java版服务器常见报错解决方案

Can't resolve hostname服务器IP输入错误,或者目前网络状态极差Connection refused: connect寻找不到服务器,或者服务器关闭中,建议检测IP是否正确Connection Timed Out服务器或者你的网络极差,或者服务器正在执行大型数据计算,例如使用Worldedit插件编辑大量方块时Failed to login: User not premium ...

weixin_32925455的博客 3万+

从零开始:手把手教你检查并更新英伟达GPU驱动和CUDA版本(Windows/Linux双平台)

本文详细指导如何在Windows和Linux系统上检查并更新英伟达GPU驱动和CUDA版本,解决版本不匹配导致的常见问题。涵盖驱动更新、CUDA Toolkit安装、版本冲突排解及性能优化技巧,帮助开发者高效管理GPU计算环境。

weixin_29237635的博客 701

Palantir的本体论建模跟数仓建模的异同

Palantir的Foundry Ontology通过构建组织的数字孪生体,将数据集和模型映射为对象类型、属性、链接和操作类型,形成完整的语义知识网络。与传统数仓建模相比,本体建模以业务问题为驱动,强调细粒度语义和实时决策能力,采用图语义技术实现灵活的映射关系。

轩哥的个人研究和成长记录 1595

Minecraft服务器连接错误排查与合规管理方案详解

在Minecraft服务器运维中,网络连接异常是常见的技术挑战。理解TCP/IP协议栈的工作原理是基础,当客户端与服务器通信时,连接建立、数据包交换和会话维持等环节都可能出现问题。从技术原理层面看,`connection reset`这类错误通常意味着TCP连接被对端异常关闭,可能源于服务器进程崩溃、防火墙规则拦截或网络设备故障。其技术价值在于帮助管理员快速定位网络层或应用层的故障点,避免服务中断。在Minecraft服务器生态中,这直接关系到玩家体验和服务器稳定性。应用场景涵盖服务器部署、日常运维和故障恢

weixin_32175665的博客 434

从平衡车到寻迹小车:IMU963RA九轴陀螺仪实战避坑与四元数融合指南

本文详细解析了IMU963RA九轴陀螺仪在机器人姿态控制中的应用,重点探讨了从六轴升级到九轴系统的技术路径及四元数融合算法。通过实战案例,揭示了如何利用地磁计补偿陀螺积分漂移,并提供硬件集成、传感器校准及算法实现的完整解决方案,有效将8小时漂移控制在2度以内。

weixin_27219587的博客 254

【独家授权】Seedance官方未发布的Prompt调优SOP手册(v2.0.3内部修订版):含17个可直接复用的导演指令模组

解决AI视频生成效果不稳定难题,本手册系统梳理Seedance 2.0导演级Prompt编写技巧与性能调优技巧。覆盖分镜控制、运镜逻辑、风格一致性等17个高频场景,提供开箱即用的导演指令模组。实测提升生成准确率与渲染效率,值得收藏。

VarChat的博客 474

注意力机制篇 | YOLOv8改进之在C2f模块添加EMA注意力机制(附2种改进方法)

EMA(Exponential Moving Average)注意力机制是一种用于增强模型性能的注意力机制,它通过对模型的特征图进行加权平均来提取更有用的特征信息。具体来说,EMA注意力机制通过引入一个权重因子来调整特征图中每个位置的重要性,从而使模型能够更好地关注重要的特征。🌈

小哥谈 4180

Onnxruntime之YOLOP部署过程记录

魔改YoloP部署过程记录

如果想成为中心,那么就到中心去吧。 1924

为有机会进大厂,程序员必须掌握的核心算法有哪些?

由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...

帅地 70万+

Aurix TC3xx系列MCU ADC模块简介(一)

简单介绍英飞凌Aurix TC3xx系列单片机ADC模块的特点及内部结构。

m0_38045338的博客 6361

程序员必须掌握的核心算法(C++)

本文完全转载如下博客地址,转载目的仅仅只是交流学习,如果侵权,请联系我,我会及时删除和处理! 转载原文地址:https://blog.youkuaiyun.com/m0_37907797/article/details/102661778 ...

净无邪博客 1635

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

算法的进阶修炼

一、算法最最基础 1、时间复杂度 2、空间复杂度 一般最先接触的就是时间复杂度和空间复杂度的学习了,这两个概念以及如何计算,是必须学的,也是必须最先学的,主要有最大复杂度、平均复杂度等,直接通过博客搜索学习即可。 文章推荐: 算法分析神器—时间复杂度 二、基础数据结构 1、线性表 列表(必学) 链表(必学) 跳跃表(知道原理,应用,最后自己实现一遍) 并查集(建议结合刷...

u011707861的博客 686

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

程序员必须掌握的核心算法有哪些(转载)

程序员必须掌握的核心算法有哪些

lili9415的博客 1777

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

程序员必须掌握的核心算法有哪些?

由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...

江湖人称黑哥的博客 259

归纳程序员必须掌握的核心算法(详细)

由于我之前一直强调数据结构...

干嘛卷来卷去的博客 2196

[转载]程序员必须掌握的核心算法有哪些?

由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不...

u013310037的博客 2161

程序员必须掌握的核心算法有哪些?数据结构与算法的C/C++/Java/C#/Python实现

原创置顶 帅地 最后发布于2019-12-26 17:54:22 阅读数 488499 收藏 展开 由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散...

Peter的博客 826

程序员基础算法学习-转载

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

Demo__的博客 533
上一篇: 监听器入门看这篇就够了(修订版)
下一篇: 过滤器入门看这一篇就够了(修订版)
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值