一 参考老师给的war包,创建相应的项目,并完成相应的测试,修改相应的内容,打上自己的标签,再导出war包。
    已完成
    二 上传相应的war包到相应的QQ目录下
    已上传
    三 小结
    j2019001001_13_servletAndFilterDemo.war
    问题1. 过滤器的配置

    1. <!-- 配置过滤器,注意,是对URL进行拦截或是过滤 -->
    2. <filter>
    3. <filter-name>MyFilter01</filter-name>
    4. <filter-class>filter.MyFilter01</filter-class>
    5. </filter>
    6. <filter-mapping>
    7. <filter-name>MyFilter01</filter-name>
    8. <url-pattern>/MyServlet</url-pattern>
    9. </filter-mapping>

    问题2.过滤器是实现
    继承Filter接口,实现接口的doFilter方法,使用chain.doFilter(request, response)放行

    public class MyFilter01 implements Filter {
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            // 相当于是模拟预设工作
            System.out.println("这是准备工作.....");
            // 放行【如果没有下面的doFilter过程,即为拦截了】,放行后可以到达servlet
            chain.doFilter(request, response);
            // 相当于是模拟善后工作【servlet工作完后,再回到这里】
            System.out.println("这是善后工作.....");
        }
    }
    

    j2019001001_14_servletAndMultiFilters.war
    问题1.启动异常

    严重: 启动过滤器异常
    java.lang.Error: Unresolved compilation problem: 
        The type MyFilter02 must implement the inherited abstract method Filter.init(FilterConfig)
    
        at filter.MyFilter02.init(MyFilter02.java:18)
        at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:281)
        at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:262)
        at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106)
        at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4538)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5181)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
    

    解决方案:根据报错提示,实现init、destory方法,添加代码如下

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

    问题2.多次过滤的配置
    当我们为一个资源设置了多个过滤器时,这些过滤器就组成一个Filter链的结构。
    当执行到一个filter的doFilter方法,调用其中的chain.doFilter()。如果还有拦截器(filter),则继续执行下一个filter的doFIlter方法,
    如果之后没有过滤器了,就放行请求。相当于调用了目标资源的service()方法。
    doFilter()方法用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个过滤器则将请求发送到目标资源。

    解答:当有多个Filter时,在web.xml中靠前的filter先执行。

      <filter>
        <filter-name>MyFilter02</filter-name>
        <filter-class>filter.MyFilter02</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>MyFilter02</filter-name>
        <url-pattern>/MyServlet</url-pattern>
      </filter-mapping>
      <filter>
        <filter-name>MyFilter01</filter-name>
        <filter-class>filter.MyFilter01</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>MyFilter01</filter-name>
        <url-pattern>/MyServlet</url-pattern>
      </filter-mapping>
    

    运行结果:
    image.png
    j2019001001_15_servletAutoLoginFilter.war
    思考1. 写死了用户名和密码,思考真实的业务场境,如何取用户名和密码判断?
    通过取request中传递过来的值得到用户名和密码,同时密码要进行加密传输,如果明文传输不安全。

    思考2. 退出业务逻辑
    首先得明白,在服务器端是不能直接删除客户端的cookie,它采取的方式是在服务端设置cookie.setMaxAge(0),
    再通过 response.addCookie(cookie) 将这个值返回到客户端后,客户端就知道自己的cookie没用了,再删除它。
    故 response.addCookie(cookie)不能省略,它是一个告知的功能。

    // 移除session
    request.getSession().removeAttribute("user");
    // 创建cookie
    Cookie cookie = new Cookie("autologin", "msg");
    cookie.setPath(request.getContextPath());
    
    // 将cookie置为过期
    cookie.setMaxAge(0);
    response.addCookie(cookie);
    

    思考3. 自动登陆
    image.png
    测试自动登陆的逻辑是没有问题的,单没有实现理想的登陆状态,也就是在有效期内不需要输入密码就自动进行登陆。
    查看代码是因为过滤器只是登录成功则将用户状态存入session域,而在LoginServlet中需要获取用户名密码才能实现登陆。
    解决方法:在登陆界面实现用户名密码的一个自动回显,然后用户点击登陆就可实现自动登录。

    j2019001001_16_servletFilterListener.war
    问题1. 客户端浏览器禁用Cookie时,如何获取session ID?
    当客户端浏览器中禁止 Cookie,Servlet 容器无法从客户端浏览器中取得作为 Cookie 的 Session ID。
    Java Servlet API 中提出了跟踪 Session 的另一种机制,如果客户端浏览器不支持 Cookie,Servlet 容器可以重写客户请求的 URL,把 Session ID 添加到 URL 信息中。

    思考1. 过滤器和控制器的差别?

    1. Servlet
    • 创建并返回一个包含基于客户端请求性质内容的完整的HTML页面
    • 创建可以嵌入到现有的HTML页面中的一部分HTML页面(HTML片段)
    • 读取客户端发来的隐藏数据
    • 读取客户端发来的显示数据
    • 与其他服务器资源(包括数据库和java的应用程序)进行通信
    • 通过状态码和响应头向客户端发送隐藏数据
    1. Filter
    • 能够在一个请求到达Servlet之前预处理用户请求,也可以在离开Servlet时处理HTTP响应。在执行Servlet之前,首先执行Filter程序 ,并为之做一些预处理工作
    • 根据程序需要修改请求和响应
    • 在Servlet被调用之后截获Servlet的执行

    思考2. 过滤器和控制器的url-pattern是什么关系?
    过滤器和控制器的url-pattern相同时,先把requet转发给filter,如果有多个filter连接在一起那么先执行过滤器链,最后执行请求servlet控制器。

    思考3. 过滤器配置时,使用通配符在url-pattern中的作用是什么?
    表示过滤该路径下的所有资源。

    思考4. 本例的监听器本质上是在监测容器的什么事件引发的什么对象的变化?
    检测session对象的创建和销毁引起HttpSessionEvent这个对象的变化。

    j2019001001_17_servletFilterListenerAllDemo.war

    思考1 本例中的javabean在哪里完成定义的?在哪里用到了?
    在cn.edu.cuit.bean.User中完成定义,在cn.edu.cuit.servlet.LoginServlet
    1.1这个javabean写得规范吗?不规范
    1.2javabean有哪些规范?

    • 必须要有一个public无参构造
    • 属性都应该是private,不应有public属性
    • 为private属性提供符合命名规范的get/set方法实现serializeable 接口

      1.3请自行将该bean改造成规范的javabean ```java public class User implements Serializable{

      public User(){} private String name = null; private String pass = null;

    public User(String name,String pass) {
        this.name = name;
        this.pass = pass;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPass() {
        return pass;
    }
    public void setPass(String pass) {
        this.pass = pass;
    }
    

    }

    思考2 过滤器链如何配置?<br />当浏览器访问Web服务器中的资源时需要经过两个过滤器Filter1和Filter2,首先Filter1会对这个请求进行拦截,在Filter1过滤器中处理好请求后,通过调用Filter1的doFilter()方法将请求传递给Filter2,Filter2将用户请求处理后同样调用doFilter()方法,最终将请求发送给目标资源。当Web服务器对这个请求做出响应时,也会被过滤器拦截,这个拦截顺序与之前相反,最终将响应结果发送给客户端。<br />在 web.xml 中,配置在前面的过滤器先执行,配置在后面的过滤器后执行。
    
    思考3 监听器如何实现相应的监听动作?
    
    1. 实现了特定接口的类为监听器,用来监听另一个Java类的方法调用或者属性改变;
    1. 当被监听的对象发生了方法调用或者属性改变后,监听器的对应方法就会立即执行。
    
    思考4 用户会话如何设置过期时间?<br />在Servlet里面获取HttpServletSession的实例,并且用“setMaxInactiveInterval()”方法来设置。
    
    思考5 服务器上,在控制器,即Servlet中实现包含和转发是如何实现的?客户端知道吗?
    ```java
    request.getRequestDispatcher("/myForward.jsp").forward(request, response);
    request.getRequestDispatcher("/myInclude.jsp").include(request, response);
    

    转发是在服务器内部进行的,对客户端来说就是一次请求,所以客户端并不知道是否进行的包含或者请求转发。

    思考6 响应对象如何实现让客户端重定向,再发请求?

    // 响应对象完成重定向,这个动作会让客户端再次发请求来完成
    response.sendRedirect(url);
    

    思考7 对于过滤器和控制器的配置,web.xml方式和注解方式,应该如何实现,应该如何选择?
    web.xml的实现方式:

      <filter>
        <filter-name>FilterChina01</filter-name>
        <filter-class>cn.edu.cuit.filterChain.FilterChain01</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>FilterChina01</filter-name>
        <url-pattern>/ServletForFilterChain</url-pattern>
      </filter-mapping>
    

    注解配置:

    @WebFilter(dispatcherTypes = {
                    DispatcherType.REQUEST, 
                    DispatcherType.FORWARD, 
                    DispatcherType.INCLUDE, 
                    DispatcherType.ERROR
            }
                        , urlPatterns = { "/*" })
    

    思考8 检测用户登录的过滤器如何实现用户对目录访问的拦截?
    获取session对象,查看session中有无user值,如果没有拦截跳转到/login/login.jsp页,如果有user值说明已经登陆,放行。

    思考9 本例中,如何检验Servlet的转发和包含动作?
    9.1请求/ForwardServlet
    image.png
    9.2请求/IncludeServlet
    image.png
    本次上机心得:
    Filter的过滤器链一开始理解并不深入,通过运行代码和对比web.xml里面的配置,才明白整个执行的流程。Listener实现统计在线用户的功能,解开了我之前一直在疑惑的问题,之前有项目用到这个功能,我们考虑的是判断seesion个数,根本没考虑到有监听器这个功能,所有基础还是非常重要的,有问题应该先去考虑是不是别人已经封装好了给了实现,也是不自己从底层开始想应该怎么做,这样效率很低并且自己也很难做好。