以后我们可以将对请求进行处理的代码放在放行之前进行处理,而如果请求完资源后还要对响应的数据进行处理时可以在放行后进行逻辑处理。
1.4 Filter拦截路径配置
拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter
注解进行配置。如:@WebFilter("拦截路径")
拦截路径有如下四种配置方式:
-
拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
-
目录拦截:/user/*:访问/user下的所有资源,都会被拦截
-
后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
-
拦截所有:/*:访问所有资源,都会被拦截
通过上面拦截路径的学习,大家会发现拦截路径的配置方式和 Servlet
的请求资源路径配置方式一样,但是表示的含义不同。
1.5 过滤器链
1.5.1 概述
过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。
如下图就是一个过滤器链,我们学习过滤器链主要是学习过滤器链执行的流程
上图中的过滤器链执行是按照以下流程执行:
-
执行
Filter1
的放行前逻辑代码 -
执行
Filter1
的放行代码 -
执行
Filter2
的放行前逻辑代码 -
执行
Filter2
的放行代码 -
访问到资源
-
执行
Filter2
的放行后逻辑代码 -
执行
Filter1
的放行后逻辑代码
以上流程串起来就像一条链子,故称之为过滤器链。
1.5.2 代码演示
- 编写第一个过滤器
FilterDemo
,配置成拦截所有资源
@WebFilter(“/*”)
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//1. 放行前,对 request数据进行处理
System.out.println(“1.FilterDemo…”);
//放行
chain.doFilter(request,response);
//2. 放行后,对Response 数据进行处理
System.out.println(“3.FilterDemo…”);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
- 编写第二个过滤器
FilterDemo2
,配置炒年糕拦截所有资源
@WebFilter(“/*”)
public class FilterDemo2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//1. 放行前,对 request数据进行处理
System.out.println(“2.FilterDemo…”);
//放行
chain.doFilter(request,response);
//2. 放行后,对Response 数据进行处理
System.out.println(“4.FilterDemo…”);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
- 修改
hello.jsp
页面中脚本的输出语句
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
hello JSP~
<%
System.out.println(“3.hello jsp”);
%>
- 启动服务器,在浏览器输入
http://localhost/filter-demo/hello.jsp
进行测试,在控制台打印内容如下
从结果可以看到确实是按照我们之前说的执行流程进行执行的。
1.5.3 问题
上面代码中为什么是先执行 FilterDemo
,后执行 FilterDemo2
呢?
我们现在使用的是注解配置Filter,而这种配置方式的优先级是按照过滤器类名(字符串)的自然排序。
比如有如下两个名称的过滤器 : BFilterDemo
和 AFilterDemo
。那一定是 AFilterDemo
过滤器先执行。
1.6 案例
1.6.1 需求
访问服务器资源时,需要先进行登录验证,如果没有登录,则自动跳转到登录页面
1.6.2 分析
我们要实现该功能是在每一个资源里加入登陆状态校验的代码吗?显然是不需要的,只需要写一个 Filter
,在该过滤器中进行登陆状态校验即可。而在该 Filter
中逻辑如下:
1.6.3 代码实现
1.6.3.1 创建Filter
在 brand-demo
工程创建 com.itheima.web.filter
包,在该下创建名为 LoginFilter
的过滤器
@WebFilter(“/*”)
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
1.6.3.2 编写逻辑代码
在 doFilter()
方法中编写登陆状态校验的逻辑代码。
我们首先需要从 session
对象中获取用户信息,但是 ServletRequest
类型的 requset 对象没有获取 session 对象的方法,所以此时需要将 request对象强转成 HttpServletRequest
对象。
HttpServletRequest req = (HttpServletRequest) request;
然后完成以下逻辑
-
获取Session对象
-
从Session对象中获取名为
user
的数据 -
判断获取到的数据是否是 null
-
如果不是,说明已经登陆,放行
-
如果是,说明尚未登陆,将提示信息存储到域对象中并跳转到登陆页面
代码如下:
@WebFilter(“/*”)
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
//1. 判断session中是否有user
HttpSession session = req.getSession();
Object user = session.getAttribute(“user”);
//2. 判断user是否为null
if(user != null){
// 登录过了
//放行
chain.doFilter(request, response);
}else {
// 没有登陆,存储提示信息,跳转到登录页面
req.setAttribute(“login_msg”,“您尚未登陆!”);
req.getRequestDispatcher(“/login.jsp”).forward(req,response);
}
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
1.6.3.3 测试并抛出问题
在浏览器上输入 http://localhost:8080/brand-demo/
,可以看到如下页面效果
从上面效果可以看出没有登陆确实是跳转到登陆页面了,但是登陆页面为什么展示成这种效果了呢?
1.6.3.4 问题分析及解决
因为登陆页面需要 css/login.css
这个文件进行样式的渲染,下图是登陆页面引入的css文件图解
而在请求这个css资源时被过滤器拦截,就相当于没有加载到样式文件导致的。解决这个问题,只需要对所以的登陆相关的资源进行放行即可。还有一种情况就是当我没有用户信息时需要进行注册,而注册时也希望被过滤器放行。
综上,我们需要在判断session中是否包含用户信息之前,应该加上对登陆及注册相关资源放行的逻辑处理
//判断访问资源路径是否和登录注册相关
//1,在数组中存储登陆和注册相关的资源路径
String[] urls = {“/login.jsp”,“/imgs/”,“/css/”,“/loginServlet”,“/register.jsp”,“/registerServlet”,“/checkCodeServlet”};
//2,获取当前访问的资源路径
String url = req.getRequestURL().toString();
//3,遍历数组,获取到每一个需要放行的资源路径
for (String u : urls) {
//4,判断当前访问的资源路径字符串是否包含要放行的的资源路径字符串
/*
比如当前访问的资源路径是 /brand-demo/login.jsp
而字符串 /brand-demo/login.jsp 包含了 字符串 /login.jsp ,所以这个字符串就需要放行
*/
if(url.contains(u)){
//找到了,放行
chain.doFilter(request, response);
//break;
return;
}
}
1.6.3.5 过滤器完整代码
-@WebFilter(“/*”)
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
//判断访问资源路径是否和登录注册相关
//1,在数组中存储登陆和注册相关的资源路径
String[] urls = {“/login.jsp”,“/imgs/”,“/css/”,“/loginServlet”,“/register.jsp”,“/registerServlet”,“/checkCodeServlet”};
//2,获取当前访问的资源路径
String url = req.getRequestURL().toString();
//3,遍历数组,获取到每一个需要放行的资源路径
for (String u : urls) {
//4,判断当前访问的资源路径字符串是否包含要放行的的资源路径字符串
/*
比如当前访问的资源路径是 /brand-demo/login.jsp
而字符串 /brand-demo/login.jsp 包含了 字符串 /login.jsp ,所以这个字符串就需要放行
*/
if(url.contains(u)){
//找到了,放行
chain.doFilter(request, response);
//break;
return;
}
}
//1. 判断session中是否有user
HttpSession session = req.getSession();
Object user = session.getAttribute(“user”);
//2. 判断user是否为null
if(user != null){
// 登录过了
//放行
chain.doFilter(request, response);
}else {
// 没有登陆,存储提示信息,跳转到登录页面
req.setAttribute(“login_msg”,“您尚未登陆!”);
req.getRequestDispatcher(“/login.jsp”).forward(req,response);
}
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
web浏览器中的javascript
- 客户端javascript
- 在html里嵌入javascript
- javascript程序的执行
- 兼容性和互用性
- 可访问性
- 安全性
- 客户端框架
window对象
-
计时器
-
浏览器定位和导航
-
浏览历史
-
浏览器和屏幕信息
-
对话框
-
错误处理
-
作为window对象属性的文档元素