学习笔记之 JAVAWEB过滤器

1.    过滤器

1.1 简介

引入:

       程序中,经常会涉及一些公用的代码, 每次都会去写,麻烦!

       例如:编码设置!

              (登陆用户的判断: 购物车页面、订单页面、会员编辑页面,都需要先判断用户是否登陆

 

过滤器:

       过滤器可以对用户的请求进行拦截,从而处理一些公用的业务操作(编码、登陆验证),处理完后, 放行用户请求。

 

 

1.2 写一个过滤器:

1.      过滤器是一个普通的java类, 实现了Filter接口

2.      交给服务器运行

3.      运行原理

a.      会对请求进行拦截

b.      处理一些公用的业务操作

c.      处理完成后,放行请求

d.      servlet处理请求过程。  (服务器处理请求及响应(servlet) )

e.      servlet处理完成后,控制权又回到过滤器。可以在请求处理完成后再处理一些业务操作

 

 

 

 

1.3 过滤器API

|-- Filter                                                          过滤器接口

       voidinit(FilterConfig filterConfig)             初始化方法,服务器启动时候执行

       voiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain)

                                                                      过滤器核心处理方法

       voiddestroy()                                          服务器停止时候,销毁当前实例

 

|-- FilterConfig                                                获取过滤器在web.xml的配置信息

       ServletContextgetServletContext()             获取一个ServletContext对象的引用

       StringgetInitParameter(java.lang.String name)    根据过滤器在web.xml中配置的初始化参数名称,获取其值

 

|-- FilterChain                                                  过滤器链接口

       voiddoFilter(ServletRequest request, ServletResponse response)  放行或转到下一个过滤器

 

1.4 过滤器配置: 拦截指定的请求

拦截指定的请求路径

       <url-pattern>/*</url-pattern>                     拦截所有的请求路径

       <url-pattern>/demo</url-pattern>        拦截指定的servlet

       <servlet-name>IndexServlet</servlet-name>              拦截指定名称的servlet

 

 

拦截指定的请求类型

              <dispatcher>REQUEST</dispatcher>          直接访问,默认是request类型

              <dispatcher>FORWARD</dispatcher>         拦截转发      

              <dispatcher>ERROR</dispatcher>              错误拦截(web.xml)

              <dispatcher>INCLUDE</dispatcher>          包含页面也执行拦截

 

 

1.5 总结原理

 

 

2.    案例

2.1 请求数据编码处理

Jsp-àservlet:  1. 获取请求数据;  2.调用servlet处理业务逻辑;  3. 跳转

每个servlet中, 都要对请求数据进行编码处理:

       处理请求数据编码:

              GET:

                     请求数据追加到utl之后

                     处理编码, 手动处理:

                            name= new String(name.getByte(“iso8859-1”),”utf-8” );

              POST:(请求数据放入请求体)

                     request.setCharacterEncoding(“utf-8”);

 

使用过滤器,统一处理编码(GET/POST),处理后在每一个servlet中不用再处理编码问题!

 

Jsp:

 

<body>

    <form action="${pageContext.request.contextPath }/index" method="get">

        用户名称:<input type="text" name="username"><br/>

       

        <input type="submit">

    </form>

  </body>

 

        

过滤器

 

/**

 * 处理编码过滤器

 * @author Administrator

 *

 */

public class EncodingFilter implements Filter{

 

    public void destroy() {

    }

 

    public void doFilter(ServletRequest req, ServletResponse res,

            FilterChain chain) throws IOException, ServletException {

 

        // 转换

        HttpServletRequest request = (HttpServletRequest) req;

        HttpServletResponse response = (HttpServletResponse) res;

       

        // 1. 处理公用的业务操作设置编码post

        request.setCharacterEncoding("UTF-8");

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

       

 

        //目标:request.getParameter("username");方法进行增强,让其可以处理get提交数据乱码问题

        // 创建增强后的request对象

        MyRequest requestWrapper = new MyRequest(request);

       

        // 2. 放行

        chain.doFilter(requestWrapper, response);

       

   

    }

   

    // request对象的增强类

    class MyRequest extends HttpServletRequestWrapper{

       

        //增强后request对象

        HttpServletRequest request;

 

        public MyRequest(HttpServletRequest request) {

            // 继承父类的方法

            super(request);

            this.request = request;

        }

       

        // 写增强方法

        public String getParameter(String name) {

            // 获取请求提交方式

            String method = request.getMethod();

            // 获取请求提交数据

            String value = request.getParameter(name);

            // 处理GET

            if ("GET".equals(method)) {

                // 手动处理GET请求数据乱码问题

                try {

                    value = new String(value.getBytes("iso8859-1"),"utf-8");

                } catch (UnsupportedEncodingException e) {

                    throw new RuntimeException(e);

                }

            }

            return value;

        }

       

    }

 

    public void init(FilterConfig filterConfig) throws ServletException {

       

    }

 

}

 

 

 

过滤器配置

 

    <!-- 过滤器配置 -->

    <filter>

        <filter-name>encodingFilter</filter-name>

        <filter-class>cn.itcast.filter.EncodingFilter</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>encodingFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>  

 

 

Servlet

// 1. 获取请求数据

        String name = request.getParameter("username");

 

 

2.2 请求脏处理处理

论坛:

       输入评论 --- > 显示评论信息 , 需要进行内容过滤!

实现:

1.      定义脏数据集合

2.      获取请求数据,验证是否存在脏数据, 如存在,则进行处理!

       在过滤器中,上面案例的基础上增加代码:

// 判断是否为脏数据 ?

            for (String str : list) {

                // 请求提交的数据中,包含脏数据  把脏数据用****替换

                if (value.contains(str)) {

                    value = value.replace(str, "****");

                    break;

                }

            }

 

 

3.      为了便于客户端输入,引入ckeditor空间!

       页面引入css:

              <!-- 引用客户端空间:ckeditor -->

       <scriptsrc="${pageContext.request.contextPath}/ckeditor/ckeditor.js"></script>

       <link href="${pageContext.request.contextPath}/ckeditor/samples/sample.css">

 

       使用:<textarea class="ckeditor"name="content"></textarea>

                    

         

 

 

2.3 (重点)过滤器实现登陆验证

IE --à  查看,列表页面

IE -à   信息录入

IE- à   删除记录

 

IEà    登陆

 

通常,在信息中,必须登陆用户才可以进行 信息录入、删除、修改等!

在信息录入、删除、修改 操作中,都要处理公共业务逻辑,判断用户是否登陆

使用过滤器技术,对指定的资源进行拦截,在判断是否登陆!

 

1.        login.jsp

 

<form action="${pageContext.request.contextPath }/user" method="post">

        用户名:<input type="text" name="username"><br/>

        密码:<input type="password" name="pwd"><br/>

        <input type="submit" value="亲,点我登陆!" />

    </form>

 

 

2. UserServlet   处理登陆业务逻辑

 

public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

       

        // 创建session

        HttpSession session = request.getSession();

        String uri = "";

 

        // 1. 获取请求参数,封装为user对象

        User user = new User();

        user.setUserName(request.getParameter("username"));

        user.setPwd(request.getParameter("pwd"));

       

        try {

            // 2. 调用service处理登陆业务逻辑

            UserService us = new UserService();

            User userInfo = us.login(user);

            // 判断

            if (userInfo != null) {

                // 登陆成功, 保存用户到session

                session.setAttribute("userInfo", userInfo);

                // 跳转到首页index.jsp

                uri = "/index.jsp";

            } else {

                // 设置登陆失败提示信息

                request.setAttribute("msg", "用户名或密码错误!");

                // 登陆失败

                uri = "/login.jsp";

            }

        } catch (Exception e) {

            uri = "/error/error.jsp";

            e.printStackTrace();

        }

        // 跳转

        request.getRequestDispatcher(uri).forward(request, response);

       

    }

 

3. UserService   处理用户模板的业务逻辑操作

 

public class UserService {

 

    public User login(User user) {

        try {

            UserDao ud = new UserDao();

            return ud.findByUser(user);

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

}

 

4. UserDao      处理登陆数据验证(没有使用数据验证)

 

public class UserDao {

 

    // 模拟登陆:只有用户名tom密码888,才可以登陆

    public User findByUser(User user){

        try {

            if ("tom".equals(user.getUserName()) && "888".equals(user.getPwd())){

                // 登陆成功,返回用户信息

                return user;

            }

            return null;

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

}

 

 

5.  Loginfilter.java     登陆验证过滤器

 

/**

 * 登陆验证过滤器:只有登陆后,才可以有权限访问首页"index.jsp"

 *

 * 过滤器

    1. 获取请求url,先放行一些资源(login.jsp)

    2. 拦截,处理公用业务

          a.获取session对象

          b.获取session中存储的用户

          c.如果用户为null,说明没有登陆,跳转到login,jsp

 */

public class LoginFilter implements Filter{

 

 

    // 过滤器处理方法

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

       

        // 转换

        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse res = (HttpServletResponse) response;

       

        //1. 获取请求url

        String uri = req.getRequestURI();

        //判断:先放行一些资源登陆, login.jsp, user(登陆处理servlet)

        if (uri.contains("/login.jsp") || uri.contains("/user") ) {

            chain.doFilter(req, res);

        } else {

            //2. 当用户访问其他资源,如:index.jsp等,需要进行登陆验证:只有登陆后,才可以访问

           

            //2.1 获取session

            HttpSession session = req.getSession(false);

            //2.2 session获取用户信息

            if (session != null) {

               

                // session中获取数据

                User user = (User) session.getAttribute("userInfo");

               

                //2.3 判断用户是否为null如为null,说明没有登陆,跳到登陆页面;否则放行资源!

                if (user == null) {

                    // 没有登陆,跳转到登陆页面

                    res.sendRedirect(req.getContextPath() + "/login.jsp");

                } else {

                    // 已经登陆,放行【在servlet处理业务后,由servlet跳转】

                    chain.doFilter(req, res);

                }

            } else {

               

                // 说明没有登陆,跳转到登陆页面

                res.sendRedirect(req.getContextPath() + "/login.jsp");

            }

       

        }

       

    }

 

    public void init(FilterConfig filterConfig) throws ServletException {

    }

   

    public void destroy() {

    }

 

}

 

过滤器配置:

<!-- 登陆验证过滤器 -->

    <filter>

        <filter-name>loginFilter</filter-name>

        <filter-class>cn.itcast.filter.LoginFilter</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>loginFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

 

 

 

2.4 用过滤器实现缓存

项目中,有些jpg、css、js, 需要进行缓存!  这样好处,不用每次请求服务器时候,都从服务器上下载jpg、css、js文件,从而提高页面响应速度!

缓存时间:

       Jpg:  1 Month

       Css: 2 Month

       Js:   3 Month

 

如何实现缓存?

       Response.setDateHeader(“expires”,-1);// 设置不缓存

       Response.setDateHeader(“expires”,缓存截止时间); // 设置缓存

 

缓存代码?

       对这个项目资源有效,所以不应该放到某个servlet中! 使用过滤器对项目的jpg、js、css资源进行拦截,从而确定缓存时间!

       缓存时间:放在web.xml中的过滤器配置中!

 

 

Style.css/index.js/5.jpg

index.js 代码

var obj = new Object();

obj.name = 'tom';

obj.show = function() {

    alert(obj.name);

}

 

 

Index.jsp

 

<!-- 引入css -->

    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/css/style.css">

    <!-- 引入js -->

    <script type="text/javascript" src="${pageContext.request.contextPath }/js/index.js"></script>

 

    <script type="text/javascript">

    obj.show();

    </script>

  </head>

 

  <body>

    <img alt="网络太差" src="${pageContext.request.contextPath }/images/5.jpg">

  </body>

 

 

 

过滤器处理缓存时间

 

 

/**

 * 过滤器:

 *      页面资源进行缓存:js/jpg/css

 * @author Administrator

 *

 */

public class CacheFilter implements Filter {

   

    // 保存服务器创建的读取过滤器配置信息的对象

    private FilterConfig config;

 

    public void destroy() {

    }

 

    // 过滤器核心处理方法

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

       

        // 转换

        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse res = (HttpServletResponse) response;

       

        // 缓存时间

        long time = 0L;// 单位:月

       

        // 1. 获取请求路径

        String uri = req.getRequestURI();

       

        // 2. 当请求路径包含jpg/css/js, 缓存

        if (uri.endsWith("jpg")) {

            time = Long.parseLong(config.getInitParameter("jpg"));

        }

        else if (uri.endsWith("js")) {

            time = Long.parseLong(config.getInitParameter("js"));

        }

        else if (uri.endsWith("css")) {

            time = Long.parseLong(config.getInitParameter("css"));

        }

        // 3. 设置缓存时间

        res.setDateHeader("expires", System.currentTimeMillis() + time*30*24*3600*1000);

       

        // 4. 放行

        chain.doFilter(request, response);

       

    }

 

    public void init(FilterConfig filterConfig) throws ServletException {

        this.config = filterConfig;

    }

 

}

 

过滤器配置:

 

    <!-- 配置缓存过滤器 -->

    <filter>

        <filter-name>cachefilter</filter-name>

        <filter-class>cn.itcast.filter.CacheFilter</filter-class>

        <!-- 配置资源的缓存时间 -->

        <init-param>

            <param-name>jpg</param-name>

            <param-value>3</param-value>

        </init-param>

        <init-param>

            <param-name>js</param-name>

            <param-value>2</param-value>

        </init-param>

        <init-param>

            <param-name>css</param-name>

            <param-value>1</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>cachefilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

 

 

 

 

 

2.5 过滤器实现数据压缩

响应头:

       location          响应资源

       content-type    响应类型

       expires           -1    缓存

       cache-control  no-cache

       program         no-cache

       refresh           刷新

       content-encoding  响应数据的压缩格式

                     gizp

 

 

 

 

数据压缩过程:

       Servlet,向浏览器输出数据, 先对数据进行压缩, 把压缩后的数据发给浏览器,浏览器解压缩,这就是数据压缩过程!

       注意:服务器通知浏览器,数据已经压缩! 设置content-encoding响应头,指定压缩格式为gzip。

 

 

为什么要用数据压缩?

 

1.      提供页面执行效率;

2.      降低成本

       大型电子商务网站对于带宽收费是按照出口流量收费,有必要把数据进行压缩后在发送给浏览器显示;  从而降低成本!

 

 

在每一个servlet中,实现数据压缩:

 

/**

 * 通过servlet向浏览器发送数据

 * @author Administrator

 *

 */

public class ContentServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        // 模拟数据

        StringBuffer sb = new StringBuffer();

        for (int i=0; i<100000; i++) {

            sb.append("abcd");

        }

        System.out.println("压缩前-->" + sb.toString().getBytes().length);

       

        /***************** 数据压缩 ********************/

        //1. 指定数据压缩位置

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        //2. 创建数据压缩工具类对象

        GZIPOutputStream gzip = new GZIPOutputStream(bos);

        //3. 数据压缩

        gzip.write(sb.toString().getBytes());

        // 输出缓冲

        gzip.close();

       

       

        //4. 获取压缩后的数据

        byte[] result = bos.toByteArray();

        System.out.println("压缩后-->" + result.length);

       

        // 指定响应头,为压缩头

        response.setHeader("content-encoding", "gzip");

        //5. 向浏览器发送数据

        response.getOutputStream().write(result);

    }

 

 

}

 

      

 

过滤器实现数据压缩:

 

/**

 * 数据压缩过滤器

 * @author Administrator

 *

 */

public class EncodingFilter implements Filter{

 

 

    // 数据压缩处理方法

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

       

        // 转换

        HttpServletResponse res = (HttpServletResponse) response;

       

        // response对象进行增强

        MyResponse responseWrapper = new MyResponse(res);

 

        // 放行

        chain.doFilter(request, responseWrapper);

       

        // 数据压缩

        // 获取response中输出的数据

        char data[] = responseWrapper.getCharrArray();

       

       

        //1. 数据压缩位置

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        //2. 压缩工具对象

        GZIPOutputStream gzip = new GZIPOutputStream(bos);

        //3. 数据压缩

        gzip.write(new String(data).getBytes());

        // 清空缓冲

        gzip.finish();

       

        //4. 获取压缩后的数据

        byte[] result = bos.toByteArray();

        System.out.println(result.length);

       

        // 设置数据压缩响应头

        res.setHeader("content-encoding", "gzip");

       

        // 输出数据

        response.getOutputStream().write(result);

       

       

    }

   

    // 创建response对象增强类

    class MyResponse extends HttpServletResponseWrapper{

 

        // 增强的对象

        private HttpServletResponse response;

        // 保存response对象中写入的字符数据(字符的缓冲区)

        private CharArrayWriter charArray = new CharArrayWriter();

       

        public MyResponse(HttpServletResponse response) {

            super(response);

            this.response = response;

        }

       

        // 重写getWriter方法

        @Override

        public PrintWriter getWriter() throws IOException {

            // response对象中写入的数据缓冲在charArray对象中

            return new PrintWriter(charArray);

        }

       

        // 返回resposne对象中的字符数据

        public char[] getCharrArray() {

            return charArray.toCharArray();

        }

       

    }

   

   

 

    public void destroy() {

       

    }

    public void init(FilterConfig filterConfig) throws ServletException {

       

    }

 

}

 

      

      

 

 

 

 

发布了51 篇原创文章 · 获赞 19 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览