【JavaWeb】Filter(293-304)

293.Filter-什么是Filter过滤器

1、Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
2、Filter 过滤器它是 JavaEE 的规范。也就是接口
3、Filter 过滤器它的作用是:拦截请求,过滤响应

拦截请求常见的应用场景有:
1、权限检查
2、日记操作
3、事务管理……等等

294.Filter-Filter过滤器的基本使用

要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必须是用户登录之后才允许访问。

思考:根据之前我们学过内容。我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以在jsp页面检查用户是否登录,可以判断 Session 中否包含有用户登录的信息即可,没有登录跳转到登录页面
问题:这种方案仅仅只能用在jsp页面中,解决方案,使用Filter

【JavaWeb】Filter(293-304)_第1张图片

Filter 的工作流程图:
【JavaWeb】Filter(293-304)_第2张图片
Filter 过滤器的使用步骤:
1、编写一个类去实现 Filter 接口
2、实现过滤方法 doFilter()
3、到 web.xml 中去配置 Filter 的拦截路径

Filter 的代码:

public class AdminFilter implements Filter {
	/**
	* doFilter 方法,专门用于拦截请求。可以做权限检查
	*/
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

		HttpSession session = httpServletRequest.getSession(); 
		Object user = session.getAttribute("user");
		// 如果等于null,说明还没有登录
		if (user == null) {
			//没有登录,跳转到登录页面
			servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
			return;
		} else {
			// 让程序继续往下访问用户的目标资源
			filterChain.doFilter(servletRequest,servletResponse);
		}
	}
}

web.xml 中的配置:


<filter>
	
	<filter-name>AdminFilterfilter-name>
	
	<filter-class>com.atguigu.filter.AdminFilterfilter-class>
filter>

<filter-mapping>
	
	<filter-name>AdminFilterfilter-name>
	
	<url-pattern>/admin/*url-pattern>
filter-mapping>

295.Filter-完整的用户登录和权限检查

login.jsp 页面 == 登录表单

这是登录页面。login.jsp 页面 <br>
<form action="http://localhost:8080/15_filter/loginServlet" method="get">
	用户名:<input type="text" name="username"/> <br>
	密	码:<input type="password" name="password"/> <br>
	<input type="submit" />
form>

LoginServlet 程序

public class LoginServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html; charset=UTF-8"); 
		String username = req.getParameter("username"); 
		String password = req.getParameter("password");

		if ("wzg168".equals(username) && "123456".equals(password)) { 
			req.getSession().setAttribute("user",username); 
			resp.getWriter().write("登录 成功!!!");
		} else {
			req.getRequestDispatcher("/login.jsp").forward(req,resp);
		}
	}
}

296.Filter-Filter的生命周期

Filter 的生命周期包含几个方法:
1、构造器方法
2、init 初始化方法
第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)

3、doFilter 过滤方法
第 3 步,每次拦截到请求,就会执行

4、destroy 销毁
第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)

297.Filter-FilterConfig类介绍

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

FilterConfig 类的作用是获取 filter 过滤器的配置内容
1、获取 Filter 的名称 filter-name 的内容
2、获取在 Filter 中配置的 init-param 初始化参数
3、获取 ServletContext 对象

java 代码:

@Override
public void init(FilterConfig filterConfig) throws ServletException { 
	System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化");
	//1、获取Filter 的名称 filter-name 的内容
	System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
	
	//2 、 获 取 在 web.xml中 配 置 的 init-param初 始 化 参 数
	System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username")); 
	System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));
	
	//3、获取ServletContext 对象
	System.out.println(filterConfig.getServletContext());
}

web.xml 配置:


<filter>
	
	<filter-name>AdminFilterfilter-name>
	
	<filter-class>com.atguigu.filter.AdminFilterfilter-class>

	<init-param>
		<param-name>usernameparam-name>
		<param-value>rootparam-value>
	init-param>

	<init-param>
		<param-name>urlparam-name>
		<param-value>jdbc:mysql://localhost3306/testparam-value>
	init-param>

filter>

298.Filter-FilterChain多个过滤器执行的细节

Filter:过滤器
Chain:链,链条
FilterChain:就是过滤器链(多个过滤器如何一起工作)
【JavaWeb】Filter(293-304)_第3张图片

299.Filter-Filter拦截器的三种配置方式

精确匹配
以下配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp

<url-pattern>/target.jspurl-pattern>

目录匹配
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*

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

后缀名匹配

<url-pattern>*.htmlurl-pattern>
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

<url-pattern>*.dourl-pattern>
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

<url-pattern>*.actionurl-pattern>
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!

300.Filter-使用Filter过滤器实现后台的权限管理

Filter 代码:

public class ManagerFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 
		Object user = httpServletRequest.getSession().getAttribute("user");
		if (user == null) {
			httpServletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletRes ponse);
		} else {
			filterChain.doFilter(servletRequest,servletResponse);
		}
}

	@Override
	public void destroy() {

	}
}

web.xml 中的配置:

<filter>
	<filter-name>ManagerFilterfilter-name>
	<filter-class>com.atguigu.filter.ManagerFilterfilter-class>
filter>
<filter-mapping>
<filter-name>ManagerFilterfilter-name>
	<url-pattern>/pages/manager/*url-pattern>
	<url-pattern>/manager/bookServleturl-pattern>
filter-mapping>

301.书城项目-ThreadLocal使用介绍

ThreadLocal 的作用,它可以解决多线程的数据安全问题。

ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)

ThreadLocal 的特点:
1、ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
2、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal 对 象 实 例 。
3、每个ThreadLocal对象实例定义的时候,一般都是static类型
4、ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放。

测试类:

public class OrderService {

	public void createOrder(){
		String name = Thread.currentThread().getName();
		System.out.println("OrderService 当前线程[" + name + "]中保存的数据是:" + 	ThreadLocalTest.threadLocal.get());
		new OrderDao().saveOrder();
	}
}

public class OrderDao {

	public void saveOrder(){
		String name = Thread.currentThread().getName(); System.out.println("OrderDao 当前线	程[" + name + "]中保存的数据是:" +
ThreadLocalTest.threadLocal.get());
	}
}

public class ThreadLocalTest {

//	public static Map data = new Hashtable();
	public static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();

	private static Random random = new Random();


public static class Task implements	Runnable {
	@Override
	public void run() {
		// 在Run 方法中,随机生成一个变量(线程要关联的数据),然后以当前线程名为key 保存到map 中
		Integer i = random.nextInt(1000);
		// 获取当前线程名
		String name = Thread.currentThread().getName(); System.out.println("线程["+name+"]生成的随机数是:" + i);
//		data.put(name,i); threadLocal.set(i);

		try { Thread.sleep(3000);
		} catch (InterruptedException e) { e.printStackTrace();
		}
		new OrderService().createOrder();

		// 在Run 方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作
		//	Object o = data.get(name);
		Object o = threadLocal.get(); System.out.println("在线程["+name+"]快结束时取出关联的数据是:" + o);
	}
}

public static void main(String[] args) {
	for (int i = 0; i < 3; i++){
		new Thread(new Task()).start();
	}
}

302.书城项目-使用ThreadLocal确保所有操作都使用同一个Connection来实现事务管理

【JavaWeb】Filter(293-304)_第4张图片

303.书城项目-使用Filter统一给所有Service方法都加上try-catch来管理事务

【JavaWeb】Filter(293-304)_第5张图片

304.书城项目-使用Tomcat统一管理异常,展示友好的错误页面

在 web.xml 中我们可以通过错误页面配置来进行管理。


<error-page>
	
	<error-code>500error-code>
	
	<location>/pages/error/error500.jsplocation>
error-page>


<error-page>
	
	<error-code>404error-code>
	
	<location>/pages/error/error404.jsplocation>
error-page>

你可能感兴趣的:(#,四,JavaWeb,Filter)