Java web开发——过滤器Filter的常见使用

打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

微信

一、基本介绍

1、概念

       Filter也称之为过滤器,通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

2、原理图

注意:filter在web程序启动的时候被创建(和servlet相似)、init()方法也只在启动的时候调用一次。

 

二、技术详情

1、入门案例

1.编写Filter

public class FilterDemo1 implements Filter {
​
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        System.out.println("filterdemo1执行前!!!");//部分1

        chain.doFilter(request, response);  //让目标资源执行,放行  部分2

        System.out.println("filterdemo1执行后!!!");    //部分3
​
    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
​
    }
    public void destroy() {
        // TODO Auto-generated method stub
​
    }
​
}

注意:假如该过滤器拦截index.jsp,如果没有部分2,那么index.jsp是不会执行的

 

说明:在部分1中可以先对request、response进行加工,来对多个资源进行处理,如解决乱码问题(这样所以的servlet都解决了)

//对request和response进行一些预处理

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");

在部分2中可以返回执行的结果,如果下一层(servlet、filter...)还没有执行完的话,2是不会执行的(参考下)

2.配置Filter

在web.xml文件中

  <filter>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>com.shen.web.filter.FilterDemo1</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

注意:这里拦截所有的url(参考servlet),即所有的资源都要先通过FilterDemo1过滤器

2、多重Filter(Filter链)

     假如现在有两个filter

1.配置文件

  <filter>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>com.shen.web.filter.FilterDemo1</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter>
    <filter-name>FilterDemo2</filter-name>
    <filter-class>com.shen.web.filter.FilterDemo2</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>FilterDemo2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

注意:谁个在前面谁个先执行(FilterDemo1先执行)

2.程序

FilterDemo1:

        System.out.println("filterdemo1执行前!!!");

        chain.doFilter(request, response);  //让目标资源执行,放行

        System.out.println("filterdemo1执行后!!!");

FilterDemo2:

        System.out.println("filterdemo2执行前~!!");
        chain.doFilter(request, response);
        System.out.println("filterdemo2执行后~!!");

ServletDemo1:

        System.out.println("servletdemo1");
        request.getRequestDispatcher("/index.jsp").forward(request, response);

3.结果

filterdemo1执行前!

filterdemo2执行前!

servletdemo1

filterdemo2执行后!

filterdemo1执行后!

3、初始化参数

1.配置

  <filter>
    <filter-name>FilterDemo3</filter-name>
    <filter-class>com.shen.web.filter.FilterDemo3</filter-class>
    <init-param>
        <param-name>xxx</param-name>
        <param-value>yyy</param-value>
    </init-param>

  </filter>

2.获取

public class FilterDemo3 implements Filter {
​
    private FilterConfig config = null;//应为初始化在init中

    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = filterConfig;
​
    }

    public void destroy() {
    }
​
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        //获取配置的初始化参数
        System.out.println(this.config.getInitParameter("xxx"));
    }   
​
}

附:所有获取方式

  • String getFilterName():得到filter的名称。
  • String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
  • Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
  • public ServletContext getServletContext():返回Servlet上下文对象的引用。

4、配置拦截类型

  <filter>
    <filter-name>FilterDemo4</filter-name>
    <filter-class>com.shen.web.filter.FilterDemo4</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>FilterDemo4</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher><!--在这里指定拦截的方式-->
  </filter-mapping>

说明:获取页面(error.jsp),只有在以错误处理的方式获取时,才会拦截,如果直接以http://local.../error.jsp 方式来访问时,是不会被拦截的。

其他类型:

REQUEST当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用
INCLUDE如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
FORWARD如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用
ERROR如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用

注意:默认是REQUEST

三、常见应用

1、禁止缓存所有动态页面

配置:

  <filter>
    <filter-name>NoCacheFilter</filter-name>
    <filter-class>com.shen.web.filter.NoCacheFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>NoCacheFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
  </filter-mapping>

代码:

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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

        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");

        chain.doFilter(request, response);
​
    }

2、缓存页面中的静态资源

配置:

  <filter-mapping>
    <filter-name>AutoLoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter>
    <filter-name>ExpiresFilter</filter-name>
    <filter-class>com.shen.web.filter.ExpiresFilter</filter-class>

    <init-param>
        <param-name>css</param-name>
        <param-value>4</param-value><!--缓存时间为4小时-->
    </init-param>

    <init-param>
        <param-name>jpg</param-name>
        <param-value>1</param-value>
    </init-param>

    <init-param>
        <param-name>js</param-name>
        <param-value>4</param-value>
    </init-param>

    <init-param>
        <param-name>bmp</param-name>
        <param-value>4</param-value>
    </init-param>

  </filter>
  
  <filter-mapping>
    <filter-name>ExpiresFilter</filter-name>
    <url-pattern>*.jpg</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
    <filter-name>ExpiresFilter</filter-name>
    <url-pattern>*.css</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
    <filter-name>ExpiresFilter</filter-name>
    <url-pattern>*.js</url-pattern>
  </filter-mapping>

代码:

//控制缓存的filter
public class ExpiresFilter implements Filter {
​
    private FilterConfig filterConfig;
​
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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

        //1.获取用户想访问的资源
        String uri = request.getRequestURI(); 

        //2.得到用户想访问的资源的后缀名
        String ext = uri.substring(uri.lastIndexOf(".")+1);

        //得到资源需要缓存的时间
        String time = filterConfig.getInitParameter(ext);
        if(time!=null){
            long t = Long.parseLong(time)*3600*1000;
            response.setDateHeader("expires", System.currentTimeMillis() + t);
        }

        chain.doFilter(request, response);
​
    }

3、实现用户自动登陆

配置:

  <filter>
    <filter-name>AutoLoginFilter</filter-name>
    <filter-class>com.shen.web.filter.AutoLoginFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>AutoLoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

页面:

登陆::

    <form action="${pageContext.request.contextPath }/servlet/LoginServlet"  method="post">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        有效期:
            <input type="radio" name="logintime" value="3600">1小时
            <input type="radio" name="logintime" value="${10*60 }">10分钟
            <input type="radio" name="logintime" value="${5*60 }">5分钟

            <br/>

        <input type="submit" value="登陆">

    </form>

显示::(message)

    ${message }

代码:

实体::(user)

public class User {
    private String username;
    private String password;
        //get和set和构造函数
}

数据库(模拟)::(MyDb)

public class MyDb {
​
    private static List list = new ArrayList();

    static{
        list.add(new User("aaa","123"));
        list.add(new User("bbb","123"));
        list.add(new User("ccc","123"));
    }

    public static List getAll(){
        return list;
    }

}

注意:密码在这里存的是明文

登陆::(LoginServlet)

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        UserDao dao = new UserDao();
        User user = dao.find(username, password);
        if(user==null){
            request.setAttribute("message", "用户名或密码不对!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return;
        }

        request.getSession().setAttribute("user", user);
        request.setAttribute("message", "恭喜,登陆成功!!");

        //发送自动登陆cookie
        sendAutoLoginCookie(request,response,user);
        request.getRequestDispatcher("/message.jsp").forward(request, response);
    }
​
    private void sendAutoLoginCookie(HttpServletRequest request, HttpServletResponse response, User user) {

        int logintime = Integer.parseInt(request.getParameter("logintime"));
        Cookie cookie = new Cookie("autologin",user.getUsername() + "." + WebUtils.md5(user.getPassword()));//“.”为分割符【md5加密后不产生.】,autologin="username.password"
        cookie.setMaxAge(logintime);
        cookie.setPath("/day18");
        response.addCookie(cookie);
    }

注意:存给cookie的是md5加密后的

Md5加密:WebUtils

public class WebUtils {
    public static String md5(String message) {
​
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte result[] = md.digest(message.getBytes());
​
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(result);
​
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
​
    }
}

过滤器::(AutoLoginFilter)

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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

        if(request.getSession().getAttribute("user")!=null){//如果用户已经登陆,直接放行
            chain.doFilter(request, response);
            return;
        }


        //1.得到用户带过来的authlogin的cookie,
        String value = null;
        Cookie cookies[] = request.getCookies();
        for(int i=0;cookies!=null && i<cookies.length;i++){
            if(cookies[i].getName().equals("autologin")){
                value = cookies[i].getValue();
            }
        }

        //2.得到 cookie中的用户名和密码 
        if(value!=null){
            String username = value.split("\\.")[0];
            String password = value.split("\\.")[1];

            //3.调用dao获取用户对应的密码
            UserDao dao = new UserDao();
            User user = dao.find(username);
            String dbpassword = user.getPassword();

            //4.检查用户带过来的md5的密码和数据库中的密码是否匹配,如匹配则自动登陆
            if(password.equals(WebUtils.md5(dbpassword))){
                request.getSession().setAttribute("user", user);
            }
        }

        chain.doFilter(request, response);
​
    }

4、解决全站乱码问题

配置:

   <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.shen.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>charset</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

代码:

//解决全站乱码问题
public class CharacterEncodingFilter implements Filter {
​
    private FilterConfig filterConfig = null;
    private String defaultCharset = "UTF-8";//设置一个默认值
​
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        String charset = filterConfig.getInitParameter("charset");
        if(charset==null){
            charset = defaultCharset;
        }

        request.setCharacterEncoding(charset);  //其实只能解决post方式
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset=" + charset);


        chain.doFilter(request, response);

    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
​
    }

    public void destroy() {
        // TODO Auto-generated method stub
​
    }
​
}

注意:以上代码实际上只能解决post方式的请求,而不能解决get方式。

5、对request进行增强

1.解决全站乱码

1.包装设计

如果想要解决get方式请求,需要采用包装类的设计思想(将request进行增强):

  • 实现与被增强对象相同的接口 
  • 定义一个变量记住被增强对象
  • 定义一个构造器,接收被增强对象
  • 覆盖需要增强的方法
  • 对于不想增强的方法,直接调用被增强对象(目标对象)的方法
//为解决全站乱码
public class CharacterEncodingFilter implements Filter {
​
    public void destroy() {
        // TODO Auto-generated method stub
​
    }
​
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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

        request.setCharacterEncoding("gb2312");
        response.setCharacterEncoding("gb2312");
        response.setContentType("text/html;charset=gb2312");


        MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
        chain.doFilter(requestWrapper, response);

​
    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
​
    }
}
​
​

class MyCharacterEncodingRequest extends HttpServletRequestWrapper{

    private HttpServletRequest request;
    public MyCharacterEncodingRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    @Override
    public String getParameter(String name) {

        try{
            String value= this.request.getParameter(name);
            if(value==null){
                return null;
            }

            if(!this.request.getMethod().equalsIgnoreCase("get")) {
                return value;
            }

            value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
            return value;

        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

2.动态代理

public class CharacterEncodingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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


        request.setCharacterEncoding("UTF-8");  //post
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");


        //request.getParamter()  requestProxy.getParameter()
        chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(),request.getClass().getInterfaces(), new InvocationHandler(){
​
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {

                if(!method.getName().equals("getParameter")){
                    return method.invoke(request, args);
                }

                if(!request.getMethod().equalsIgnoreCase("get")){
                    return method.invoke(request, args);
                }

                //getParameter get
                String value = (String) method.invoke(request, args);
                if(value==null){
                    return null;
                }

                return new String(value.getBytes("iso8859-1"),"UTF-8");
            }

        }), response);  

​
    }

​
    public void destroy() {}
    public void init(FilterConfig filterConfig) throws ServletException {}
​
}

2.对脏话进行处理

//脏话过滤器
public class DirtyFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
​

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        DirtyRequest dirtyrequest = new DirtyRequest(request);

        chain.doFilter(dirtyrequest, response);
    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }
}
​
class DirtyRequest extends HttpServletRequestWrapper{
​
    private List<String> dirtyWords = Arrays.asList("傻B","操蛋","畜生");
    private HttpServletRequest request;
    public DirtyRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    @Override
    public String getParameter(String name) {

        String value = this.request.getParameter(name);
        if(value==null){
            return null;
        }

        for(String dirtyWord : dirtyWords){
            if(value.contains(dirtyWord)){
                value = value.replace(dirtyWord, "****");
            }
        }
        return value;
    }
}

3.对HTML元素进行处理

//html转义过滤器
public class HtmlFilter implements Filter {
​
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
​
        MyHtmlRequest myrequest = new MyHtmlRequest(request);
        chain.doFilter(myrequest, response);

    }
    public void destroy() {
        // TODO Auto-generated method stub
​
    }
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
​
    }
}
​
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);
        if(value==null){
            return null;
        }
        return 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());
​
        }   
}

6、对response进行增强

1.全站压缩

1.包装设计模式

//解决全站压缩
public class GzipFilter implements Filter {
​
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

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

        BufferResponse myresponse = new BufferResponse(response);

        chain.doFilter(request, myresponse);


        //拿出缓存中的数据,压缩后再打给浏览器
        byte out[] = myresponse.getBuffer();
        System.out.println("原始大小:" + out.length);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        GZIPOutputStream gout = new GZIPOutputStream(bout);
        gout.write(out);
        gout.close();


        byte gzip[] = bout.toByteArray();
        System.out.println("压缩后的大小:" + gzip.length);


        response.setHeader("content-encoding", "gzip");
        response.setContentLength(gzip.length);
        response.getOutputStream().write(gzip);
    }

    public void destroy() {
    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
​
class BufferResponse extends HttpServletResponseWrapper{
​
    private ByteArrayOutputStream bout = new ByteArrayOutputStream();

    private PrintWriter pw;
    private HttpServletResponse response;
    public BufferResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyServletOutputStream(bout);
    }
    @Override
    public PrintWriter getWriter() throws IOException {
        pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));  //PrintWriter.write(中国) <br>,要指定码表,不然可能乱码!!!!!!!!!!!!
        return pw;
    }

    public byte[] getBuffer(){
        try{
            if(pw!=null){
                pw.close();
            }
            if(bout!=null){
                bout.flush();
                return bout.toByteArray();
            }


            return null;
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
​
class MyServletOutputStream extends ServletOutputStream{
​
    private ByteArrayOutputStream bout;
    public MyServletOutputStream(ByteArrayOutputStream bout){
        this.bout = bout;
    }

    @Override
    public void write(int b) throws IOException {
        this.bout.write(b);
    }
}

2.动态代理技术

public class GzipFilter implements Filter {
​
    public void destroy() {
        // TODO Auto-generated method stub
​
    }
​
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
​

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

        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
        final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8"));

        //response.getWriter().write("aaa");  responseProxy
        chain.doFilter(request, (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(), response.getClass().getInterfaces(), new InvocationHandler(){
​
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                if(method.getName().equals("getWriter")){
                    return pw; 
                }else if(method.getName().equals("getOutputStream")){  //servletOutputStream
                    return new MyServletOutputStream(bout);
                }else{
                    return method.invoke(response, args);
                }
            }
        }));


        pw.close();
        byte result[] = bout.toByteArray();  //拿到目标资源的输出
        System.out.println("原始大小:" + result.length);

        ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
        GZIPOutputStream gout = new GZIPOutputStream(bout2);
        gout.write(result);
        gout.close();

        byte gzip[] = bout2.toByteArray();  //拿到目标资源输出的压缩数据
        System.out.println("压缩大小:" + gzip.length);

        response.setHeader("content-encoding", "gzip");
        response.setContentLength(gzip.length);
        response.getOutputStream().write(gzip);


    }
​
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
​
    }
}
​
class MyServletOutputStream extends ServletOutputStream{
​

    private ByteArrayOutputStream  bout = null;
    public MyServletOutputStream(ByteArrayOutputStream  bout){
        this.bout = bout;
    }
    @Override
    public void write(int b) throws IOException {
        bout.write(b);
    }

}

2.缓存数据到内存

     对于页面中很少更新的数据,例如商品分类,为避免每次都要从数据库查询分类数据,因此可把分类数据缓存在内存或文件中,以此来减轻数据库压力,提高系统响应速度。

//缓存数据到内存
public class CachedFilter implements Filter {
​
    private Map<String,byte[]> map = new HashMap<String,byte[]>();
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //1.得到用户请求的uri
        String uri = request.getRequestURI();
        //2.看缓存中有没有uri对应的数据
        byte b[] = map.get(uri);
        //3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回
        if(b!=null){
            response.getOutputStream().write(b);
            return;
        }
        //4.如果缓存没有,让目标资源执行,并捕获目标资源的输出
        BufferResponse1 myresponse = new BufferResponse1(response);
        chain.doFilter(request, myresponse);
        byte out[] = myresponse.getBuffer();
        //5.把资源的数据以用户请求的uri为关键字保存到缓存中
        map.put(uri, out);
        //6.把数据打给浏览器
        response.getOutputStream().write(out);
    }
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void destroy() {
    }
}

class BufferResponse1 extends HttpServletResponseWrapper{​
    private ByteArrayOutputStream bout = new ByteArrayOutputStream();  //捕获输出的缓存
    private PrintWriter pw;
    private HttpServletResponse response;
    public BufferResponse1(HttpServletResponse response) {
        super(response);
        this.response = response;
    }
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyServletOutputStream1(bout);
    }
    @Override
    public PrintWriter getWriter() throws IOException {
        pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
        return pw;
    }
    public byte[] getBuffer(){
        try{
            if(pw!=null){
                pw.close();
            }
            return bout.toByteArray();
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
class MyServletOutputStream1 extends ServletOutputStream{
    private ByteArrayOutputStream bout;
    public MyServletOutputStream1(ByteArrayOutputStream bout){  //接收数据写到哪里
        this.bout = bout;
    }
    @Override
    public void write(int b) throws IOException {
        bout.write(b);
    }
}

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
完整全套资源下载地址:https://download.csdn.net/download/qq_27595745/70761177 【完整课程列表】 完整版Java web开发教程PPT课件 Java开发进阶教程 第01章 JavaScript简介以及基本语法(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第02章 Dom模型,控制客户端元素(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第03章 表单验证,常用函数(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第04章 自定义web服务器(共14页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第06章 SERVLET(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第07章 JSP语法及运行过程(共13页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第08章 JSP内置对象(共22页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第09章 jstl、el、java bean(共18页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第10章 过滤器、监听器、自定义标签(共19页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第11章 AJAX实现(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第12章 自定义mvc框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第13章 spring ioc aop(共18页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第14章 spring mvc介绍,原理以及搭建(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第15章 spring mvc核心对象拦截器(共26页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第17章 自定义orm框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第18章 mybatis框架的搭建以及应用(共13页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第19章 mybatis高级应用(共21页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第20章 数据库连接池,缓存(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第22章 常用框架的介绍以及环境搭建(共16页).pptx JS课程案例ebookHTML\网上书店需求文档.doc

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

盡盡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值