J2EE 第三周(03.19-03.25)

1.关于用户授权的Filter例子

  用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。

  LoginFilter.java

package com.ljq.servlet;  
  
import java.io.IOException;  
  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
  
public class LogFilter implements Filter {  
    // FilterConfig可用于访问Filter的配置信息  
    private FilterConfig config;  
  
    // 实现初始化方法  
    public void init(FilterConfig config) {  
        this.config = config;  
    }  
  
    // 实现销毁方法  
    public void destroy() {  
        this.config = null;  
    }  
  
    // 执行过滤的核心方法  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        // ---------下面代码用于对用户请求执行预处理---------  
        // 获取ServletContext对象,用于记录日志  
        ServletContext context = this.config.getServletContext();  
        long before = System.currentTimeMillis();  
        System.out.println("开始过滤...");  
        // 将请求转换成HttpServletRequest请求  
        HttpServletRequest hrequest = (HttpServletRequest) request;  
        // 记录日志  
        context.log("Filter已经截获到用户的请求地址: " + hrequest.getServletPath());  
        // Filter只是链式处理,请求依然放行到目的地址  
        chain.doFilter(request, response);  
          
        // ---------下面代码用于对服务器响应执行后处理---------  
        long after = System.currentTimeMillis();  
        // 记录日志  
        context.log("过滤结束");  
        // 再次记录日志  
        context.log("请求被定位到" + hrequest.getRequestURI() + "所花的时间为: "  
                + (after - before));  
    }  
  
}  

  web.xml

<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
    <filter>  
        <filter-name>LogFilter</filter-name>  
        <filter-class>com.ljq.servlet.LogFilter</filter-class>  
    </filter>  
  
    <filter-mapping>  
        <filter-name>LogFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
  
    <welcome-file-list>  
        <welcome-file>index.jsp</welcome-file>  
    </welcome-file-list>  
</web-app>  

2.了解session

2.1Session简单介绍

  Session代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的。Session是一种服务器端的机制,Session 对象用来存储特定用户会话所需的信息。在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。Session由服务端生成,保存在服务器的内存、缓存、硬盘或数据库中。Session技术把用户的数据写到用户独占的session中。Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

2.2 Session工作原理

  1.创建Session

  当用户访问到一个服务器,如果服务器启用Session,服务器就要为该用户创建一个SESSION,在创建这个SESSION的时候,服务器首先检查这个用户发来的请求里是否包含了一个SESSION ID,如果包含了一个SESSION ID则说明之前该用户已经登陆过并为此用户创建过SESSION,那服务器就按照这个SESSION ID把这个SESSION在服务器的内存中查找出来(如果查找不到,就有可能为他新创建一个),如果客户端请求里不包含有SESSION ID,则为该客户端创建一个SESSION并生成一个与此SESSION相关的SESSION ID。这个SESSION ID是唯一的、不重复的、不容易找到规律的字符串,这个SESSION ID将被在本次响应中返回到客户端保存,而保存这个SESSION ID的正是COOKIE,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。 

  2、使用Session

  我们知道在IE中,我们可以在工具的Internet选项中把Cookie禁止,那么会不会出现把客户端的Cookie禁止了,那么SESSIONID就无法再用了呢?找了一些资料说明,可以有其他机制在COOKIE被禁止时仍然能够把Session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把Session id直接附加在URL路径的后面一种是作为URL路径的附加信息,表现形式为: http://…./xxx;jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764; 另一种是作为查询字符串附加在URL后面,表现形式为: http://…../xxx?jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 还有一种就是表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把Session id传递回服务器。

2.3 Session的作用

  Session的根本作用就是在服务端存储用户和服务器会话的一些信息。典型的应用有:

  1. 判断用户是否登录。
  2. 购物车功能。

3.异步处理

  在Servlet组件接收到的每个请求都会产生一个线程来处理请求并返回响应,当客户端的请求处理是一项比较耗时的过程,当有大量用户请求此Servlet时,Web容器中就会产生大量的线程,导致Web容器性能急剧下降。为了解决这一问题,Servlet提供了对请求的异步处理支持。

  异步处理请求的过程为:当Servlet接收到请求之后,首先需要对请求携带的数据进行一些预处理;接着,Servlet线程将请求转交给一个异步线程来执行业务处理,线程本身则返回至容器并可以处理其它客户端的请求,此时Servlet并没有差生响应数据,异步处理完业务以后,可以直接生成响应数据,或者将请求继续转发给其它Servlet。这样,Servlet线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。

  使用异步处理,必须要配置相应的部署文件,在web.xml中通过使用<async-supported>标签设置是否需要启用异步处理支持,true表示支持,false表示不支持。当然我们也可以用注解的方式来替代在web.xml中的配置。注解则需要使用asyncSupported属性来支持异步处理。

  比如:

package com.yl.servlet;  
  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.Date;  
  
import javax.servlet.AsyncContext;  
import javax.servlet.ServletException;  
import javax.servlet.annotation.WebServlet;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
/** 
 * Servlet组件异步处理请求特性的演示小程序 
 *  
 * @author LYYL 
 * 
 */  
//通过注解的方式配置,支持异步处理请求  
@WebServlet(name="servlet", urlPatterns={"/asyncServlet"}, asyncSupported=true)  
public class AsyncServlet extends HttpServlet{  
  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException {  
        processRequest(req, resp);  
    }  
  
    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException {  
        processRequest(req, resp);  
    }  
      
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException{  
        response.setContentType("text/html;charset=UTF-8");  
        PrintWriter pw = response.getWriter();  
        pw.println("进入Servlet的时间是:" + new Date() + ".");  
        pw.flush();  
          
        //在子线程中执行业务逻辑,并由其负责输出响应,主线程退出  
        AsyncContext act = request.startAsync();  
        //创建一个模拟业务逻辑执行的线程  
        Executor ec = new Executor(act);  
        Thread td = new Thread(ec);  
        td.start();  
          
        pw.println("<br>");  
        pw.println("结束Servlet的时间是: " + new Date() + ".");  
        pw.flush();   
    }  
    /** 
     * 内部类,模拟线程执行的业务逻辑 
     *  
     * @author LYYL 
     * 
     */  
    public class Executor implements Runnable{  
        private AsyncContext act = null;  
          
        /** 
         * @param act 
         */  
        public Executor(AsyncContext act) {  
            this.act = act;  
        }  
  
        @Override  
        public void run() {  
            try {  
                Thread.sleep(3000);  
                PrintWriter pw = act.getResponse().getWriter();  
                pw.println("<br>");  
                pw.println("业务执行完的时间是: " + new Date() + ".");  
                pw.flush();  
                act.complete();  
                pw.close();  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } catch (IOException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
          
    }  
}  

最终效果,Servlet开始和结束时间基本一致,而异步线程结束的时间也就是该Servlet执行完业务逻辑的时间是我们设定的3秒之后。

参考:https://blog.csdn.net/yanglun1/article/details/46456521

原文地址:https://www.cnblogs.com/cactus20/p/8649746.html