过滤器、监听器、Servlet3.0注解

一、过滤器

1.介绍

Filter 的完整流程: Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再 对服务器响应进行后处理。在一个 web 应用中,可以开发编写多个Filter,这些 Filter 组合 起来称之为一个 Filter 链。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsJrVIMB-1582630865316)(C:\Users\Hello Word\AppData\Roaming\Typora\typora-user-images\1582629150766.png)]

2.实现

init(), doFilter(), destroy()分别在相应的时机执行。后期观察生命周期。

Filter 的实现只需要两步:

Step1: 编写 java 类实现 Filter 接口,并实现其 doFilter 方法。

Step2: 在 web.xml 文件中对编写的 filter 类进行注册,并设置它所能拦截的资源

public class Filter01 implements Filter {

	/**
	 * 初始化
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("Filter01 init...");
		
	}

	/**
	 * 处理请求的拦截方法
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		// 处理请求
		System.out.println("Filter01  处理请求...");
		
		// 放行资源
		chain.doFilter(request, response);
		
		// 处理响应
		System.out.println("Filter01  处理响应...");
		
	}

	/**
	 * 销毁方法
	 */
	@Override
	public void destroy() {
		System.out.println("Filter01 destroy...");
		
	}

}


//web.xml配置
<filter>
  	<filter-name>Filter01</filter-name> <!-- 给服务器看的,与filter-mapping标签中filter-name保持一致 -->
  	<filter-class>com.shsxt.filter.Filter01</filter-class> <!-- 类的全路径 -->
  </filter>
  <filter-mapping>
  	<filter-name>Filter01</filter-name> <!-- 给服务器看的,与filter标签中filter-name保持一致 -->
  	<url-pattern>/Servlet01</url-pattern> <!-- 给浏览器看的,需要拦截的资源路径 -->
  	<!-- <servlet-name>Servlet01</servlet-name> --> <!-- 想要拦截的servlet名称,与servlet标签的servlet-name一致 -->
  </filter-mapping>

3.过滤器的执行顺序

过滤器

​ 拦截请求到达指定资源之前的请求数据

​ 拦截响应到达客户端之前的响应数据

​ 放行资源(chain.doFilter(request,response))

过滤器链

多个过滤器同时执行

执行顺序:web.xml配置文件中,先配置的先执行

拦截顺序:按照指定顺序拦截,按照相反顺序响应

​ 请求:(1 -> 2 -> 3 )

​ 响应:(3 -> 2 -> 1 )

4.过滤器实例

/**
 * 非法访问拦截
 * 	当用户访问登录状态才能访问的资源时,如果用户未登录,会被拦截到登录页面
 * 	
 * 	拦截的资源:
  		拦截所有资源  /*
  		
  	需要放行的资源:
  		1、指定页面,放行
  			无需登录即可访问的页面 (例如:登录页面、注册页面等)
  		2、静态资源,放行
  			js文件、css文件及图片(存放在statics目录下的资源)
  		3、指定操作,放行
  			无需登录即可执行的操作 (登录操作、注册操作等)
  		4、登录状态,放行
  			判断session作用域中是否存在用户数据(有数据=登录状态;无数据=非登录状态)
 		
 		当用户未登录时访问资源,拦截跳转到登录页面
 */
public class LoginAccessFilter implements Filter {
    
    public LoginAccessFilter() {
        
    }

	public void destroy() {
		
	}
	
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {
		
		// 基于HTTP
		HttpServletRequest request = (HttpServletRequest)arg0;
		HttpServletResponse response = (HttpServletResponse)arg1;
		
		// 获取当前访问的资源路径
		String path = request.getRequestURI(); // 从端口号后开始(不包含端口),到"?"前面	/站点名/资源路径
		System.out.println(path);
		
		// 1、指定页面,放行       无需登录即可访问的页面 (例如:登录页面、注册页面等)
		if (path.contains("/login.html")) {
			// 放行资源
			chain.doFilter(request, response);
			return;
		}
		
		// 2、静态资源,放行         js文件、css文件及图片(存放在statics目录下的资源)
		if (path.contains("/statics")) {
			// 放行资源
			chain.doFilter(request, response);
			return;
		}
		
		// 3、指定操作,放行        无需登录即可执行的操作 (登录操作、注册操作等)
		if (path.indexOf("/loginServlet") != -1) {
			// 放行资源
			chain.doFilter(request, response);
			return;
		}
		
		// 4、登录状态,放行 	判断session作用域中是否存在用户数据(有数据=登录状态;无数据=非登录状态)
		String user = (String) request.getSession().getAttribute("user");
		if (user != null && !"".equals(user)) {
			// 放行资源
			chain.doFilter(request, response);
			return;
		}
		
		// chain.doFilter(request, response);
		
		// 拦截请求跳转到登录页面
		response.sendRedirect("login.html");
	
	}

	public void init(FilterConfig fConfig) throws ServletException {
		
	}

}


/**
 * 用户登录
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("用户登录...");
		
		// 接收参数
		System.out.println(request.getParameter("uname"));
		
		// 模拟用户在登录状态
		request.getSession().setAttribute("user", "zhangsan");
		
		// 登录成功
		response.sendRedirect("index.html");
	}

}

二、监听器

1.介绍

web 监听器是一种Servlet 中的特殊的类,ServletContext,HttpSession,ServletRequest 的创建和销毁;变量的创建、销毁和修改等。

2.实现

public class Listener01 implements HttpSessionListener,HttpSessionAttributeListener {

	/**
	 * session的创建
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println("Session Create...");
	}

	/**
	 * session的销毁
	 */
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		System.out.println("Session Destroy...");
	}

	/**
	 * 设置域对象
	 */
	@Override
	public void attributeAdded(HttpSessionBindingEvent se) {
		System.out.println("attributeAdded...");
		
	}

	/**
	 * 删除域对象
	 */
	@Override
	public void attributeRemoved(HttpSessionBindingEvent se) {
		System.out.println("attributeRemoved...");
		
	}

	/**
	 * 修改域对象
	 */
	@Override
	public void attributeReplaced(HttpSessionBindingEvent se) {
		System.out.println("attributeReplaced...");
		
	}

}

//servlet

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 创建session对象
		HttpSession session  = request.getSession();
		
		// 设置域对象
		session.setAttribute("uname", "zhangsan");
		
		// 修改域对象
		session.setAttribute("uname", "lisi");
		
		// 删除域对象
		session.removeAttribute("uname");
		
		// session的销毁
		session.invalidate();
	}

3.监听器案例

/**
 * 在线人数统计
 * 	当有新的session对象被创建,则在线人数+1;
 * 	有session对象被销毁,在线人数-1;
 * @author Lisa Li
 *
 */
public class OnlineListener implements HttpSessionListener {
	
	// 默认在线人数
	private Integer onlineNumber = 0;

	/**
	 * 当有新的session对象被创建,则在线人数+1;
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// 人数+1
		onlineNumber++;
		// 将人数存到session作用域中
		//se.getSession().setAttribute("onlineNumber", onlineNumber);
		// 将人数存到application作用域中
		se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
		
	}

	/**
	 * 有session对象被销毁,在线人数-1;
	 */
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// 人数-1
		onlineNumber--;
		// 将人数存到session作用域中
		// se.getSession().setAttribute("onlineNumber", onlineNumber);
		// 将人数存到application作用域中
		se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
		
	}

}

/**
 * 在线人数统计
 */
public class OnlineServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	//引入日志
	//private logger logger=LoggerFactory.getLogger(OnlineServlet.class);
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//得到参数
		String key=request.getParameter("key");
		
		//判断是否为空
		if(key==null || "".equals(key)){
			//创建session对象
			HttpSession session=request.getSession();
			//获取session作用域中人数application
			Integer onlineNumber=(Integer) session.getServletContext().getAttribute("onlineNumber");
			//当前访问用户的ip及内容
			String ip=request.getRemoteAddr();
			String content=request.getParameter("content");
			System.out.println(ip);
			System.out.println(content);
			//输出
			response.setContentType("text/html;charset=UTF-8");
			response.getWriter().write("<h2>在线人数:"+onlineNumber+"</h2><h4><a href='Servlet01?key=logout'>退出</a><h4>");
			
		}else{
			//传递了参数,表示要做用户推出操作
			request.getSession().invalidate();
		}
	}

}

三、Servlet3.0注释

1.@WebServlet

@WebServlet 注解将一个继承于javax.servlet.http.HttpServlet 的类标注为可以处理用户请求的 Servlet。

//@WebServlet(value="/Servlet01")
//@WebServlet(name="Servlet01",value="/Servlet01")
//@WebServlet(value={"/Servlet01","/Servlet001"})
//@WebServlet(urlPatterns="/s01")
//@WebServlet(urlPatterns={"/Servlet01","/Servlet001"})
@WebServlet("/s01")
public class Servlet01 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("Servlet...");
		
	}

}

2.@WebFilter

使用注解时:过滤器链按照类名的字母排序(大部分情况)

@WebFilter("/*")
public class Filter01 implements Filter {

    /**
     * Default constructor. 
     */
    public Filter01() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("Filter01...");
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

3.@WebListener

Servlet3.0 提供@WebListener 注解将一个实现了特定监听器接口的类定义为监听

器。将实现了 ServletContextListener 接口的 MyServletContextListener 标注为监听器。

@WebListener
public class Listener01 implements HttpSessionListener {

    /**
     * Default constructor. 
     */
    public Listener01() {
        // TODO Auto-generated constructor stub
    }

	/**
     * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
     */
    public void sessionCreated(HttpSessionEvent se)  { 
         // TODO Auto-generated method stub
    }

	/**
     * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
     */
    public void sessionDestroyed(HttpSessionEvent se)  { 
         // TODO Auto-generated method stub
    }
	
}

4.@MultipartConfig

文件上传

  • @MultipartConfig 一定要加注解!!!!!

  • 如果前台的表单类型设置为enctype=" multipart/form-data",后台servlet一定要加注解,否则所有的参数都为null。

    使用注解@MultipartConfig 将一个 Servlet 标识为支持文件上传。 Servlet3.0 将 multipart/form-data 的 POST 请求封装成 Part,通过Part 对上传的文件进行操作。

    @MultipartConfig
    @WebServlet("/uploadServlet")
    public class UploadServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    
    	
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		// 获取参数
    		String uname = request.getParameter("uname");
    		System.out.println(uname);
    						
    		
    		
    		// 得到要上传的文件对象   getPart(name):name代表的是表单元素file文件域的name属性值
    		Part part = request.getPart("myfile");
    		// 得到文件存放的路径
    		String path  = request.getServletContext().getRealPath("/");
    		// 得到上传的文件名
    		String fileName = part.getSubmittedFileName();
    		// 上传
    		part.write(path +"/"+fileName);
    		
    		
    	}
    
    }
    
    <body>
    
    	<!-- 
    		表单实现文件上传
    			第一步:设置表单类型 enctype="multipart/form-data" (文件上传表单)
    			第二步:表单提交类型 method="POST"
    			第三步:文件域file元素设置name属性值
    	 -->
    	 <form action="uploadServlet" method="POST" enctype="multipart/form-data" >
    	 	姓名:<input type="text" name="uname" /> <br>
    	 	文件:<input type="file" name="myfile" /> <br>
    	 	<button>提交</button>
    	 </form>
    </body>
    
发布了32 篇原创文章 · 获赞 2 · 访问量 1269

猜你喜欢

转载自blog.csdn.net/qq_41128049/article/details/104503754
今日推荐