过滤器可以有多个,顺序是按照声明的顺序来的,如果前面的过滤器没有选择放行,那么他就不会通过接下来的
过滤器。
延伸知识点:会话结束两种方式,一,关闭浏览器,二,session过期。
1,会先写一个登录界面,也就是login.jsp,从这个界面跳转到login.servlet。
2,在login.servlet里面主要实现三个功能,
第一步要获取前端的数据,
String username = req.getParameter("username");
String pass = req.getParameter("pass");
第二步判断数据是否正确,有可能涉及到数据库
if ("pfdu".equals(username) && "123".equals(pass)) {
// 登录成功
// 跳转到首页// 在会话中保存一个变量,来表示用户已经登录
HttpSession session = req.getSession();
session.setAttribute("islogin", true);
// 重定向
resp.sendRedirect("main/index.jsp");
} else {
// 登录失败
// 重新回到登录页面
// 回到上一页面?
// 表示控制浏览器窗口,返回上一页面,效果和用户点击了返回按键是一样的
resp.getWriter().print("<script>window.history.back()</script>");
}
3,<!-- 在jsp中判断session中是否存在isLogin,并且还为true。 -->
不使用过滤器的话,会造成代码大量的重复,过滤器的位置就是在浏览器与servlet和jsp之间
例如:浏览器到过滤器到servlet。
过滤器可以动态拦截请求和响应。
=================================================================
不使用过滤器的话,会造成代码大量的重复,过滤器的位置就是在浏览器与servlet和jsp之间
例如:浏览器到过滤器到servlet。
过滤器:
Filter是一个接口,我们需要自定义一个类实现这个接口。
过滤器可以动态的拦截请求和响应
过程:浏览器---过滤器---servlet,HTML,jsp。
过滤器能做的事情:一,登录的逻辑判断,2,统一编码,3,敏感词汇检查,4,统计页面访问量。
解决乱码问题:
1表单中填写中文进行提交,servlet获取数据为乱码req.setCharacterEncoding("utf-8");
过滤器执行优先于servlet,jsp,html等文件。当用于访问tomcat下的某一个资源路径,首先执行到过滤器,过滤器可以拦截,或者放行。实现Filter的方法中默认是拦截的,如果想要放行通过
过滤器的实现:
1,自定义类实现与Filter接口并实现方法init();
doFilter();detory();方法。
// 进行过滤动作,只要有请求通过此过滤器,那么过滤器的doFilter方法就行执行
// 共有三个参数,第一个参数是请求,第二个参数是响应,第三个参数是用于放行请求的
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {// 如果过滤器中什么都不写,没有调用放行的方法的情况下,过滤器默认拦截,意味着请求无法到达具体的资源
System.out.println("doFilter");
// 这就话表示放行请求,意味着请求通过了过滤器,并且还能够到达具体的资源
// arg2.doFilter(arg0, arg1);
// 需求:现过滤器的范围是/main/*但是,我们想要对html单独的做处理
// 获取当前请求路径,判断路径后缀的方式,使用if else分开处理
// ServletRequest是HttpServletRequest的父接口
HttpServletRequest request = (HttpServletRequest) arg0;
String requestURI = request.getRequestURI();
System.out.println(requestURI);
if (requestURI.endsWith(".html")) {
// 这里是模拟,url-paratern比较复杂,
// 通过web.xml中的指定已经不能精确的满足我们的需要的时候,
// 我们可以通过路径进行判断满足我们的需求
2,在web.xml中配置Filter。(像servlet类似)
<!-- 类似servlet ,若使用servlet标签就把对应的class当做servlet处理,若使用filter对应的class当做过滤器处理 -->
<filter>
<filter-name>first</filter-name>
<filter-class>com.qfedu.web.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>first</filter-name>
<!-- 在servlet-mapping中表示的servlet的路径 -->
<!-- 是否是设置过滤器的路径的?过滤器没有路径,因为过滤器根本不是让用户访问, 而是在服务器运行中提供对请求和响应拦截检查处理功能的,所以过滤器没有路径 -->
<!-- url-pattern表示过滤器的范围,只要访问在范围下的任何资源,请求到达之前都会首先通过此过滤器 -->
<!--<url-pattern>/*</url-pattern> -->
<!-- 指定到具体某一个资源 <url-pattern>/index.html</url-pattern> -->
<!-- 当前项目中没有main文件夹,但是有一个servlet,那么这个servlet的路径可以指定为/main/login -->
<!-- /main/*指的是在main路径下一层级的所有资源,包括路径为/main/login -->
<!--<url-pattern>/main/*</url-pattern> -->
<!-- 所有以html结尾的文件访问的通过当前的过滤器 -->
<!-- <url-pattern>*.html</url-pattern> -->
<!-- 这种方式不支持,不支持一个url-pattern中即使用目录的方式,又使用后缀的方式 -->
<!-- <url-pattern>/main/*.html</url-pattern> -->
<url-pattern>/main/*</url-pattern>
</filter-mapping>
<!-- 一个过滤器对应多个url-pattern,多个mapping之间是一个并集关系,满足任何一个都会通过过滤器 -->
<filter-mapping>
<filter-name>first</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
设置编码字符集:
web.xml配置:
<!-- 我们把需要指定的字符集编码当做一个初始化参数传入过滤器 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.qfedu.web.EncodingFilter</filter-class>
<!-- 指定初始化参数 -->
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器内容:
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// 1设置编码
arg0.setCharacterEncoding(encode);
// 2放行
arg2.doFilter(arg0, arg1);
}
// FilterConfig就是封装了init-param中的键值对(类似于servletconfig)
@Override
public void init(FilterConfig arg0) throws ServletException {
encode = arg0.getInitParameter("encode");
}
判断是否登录
过滤器代码:
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)throws IOException, ServletException {
// 判断用户是否已经登录
// 因为在登录成功之后我们在session中保存了一个islogin
// 这里可以通过读取islogin是否为空来判断是否已经登录
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
HttpSession session = request.getSession();
if (session.getAttribute("islogin") == null) {
// 没有登录过,直接访问main下面的资源
// 跳转到登录页面重新登录
// 假设我们采用相对路径方式进行页面跳转,相对于谁?
// 过滤器根本没有路径,相对于过滤器当前处理的请求的路径
// 我们当前的过滤器的范围是main/*
// 比如当前是main/index.jsp
response.sendRedirect("../login.jsp");
} else {
// 用户登录过
// 放行
arg2.doFilter(arg0, arg1);
xml配置:
<!-- 如果auther放在encode的上面,会出现如果没有登录就不能进行编码设置的情况 -->
<!-- 但是编码的过滤器提供的功能是不管登录成功与否都能够使用的,所以我们需要注意过滤器上下书写顺序 -->
<!-- 就把过滤器想象成城墙,资源就是宝藏,可能有内城外城,chain.dofiter就是打开城门,没有这句话就是关闭城门 -->
<filter>
<filter-name>auther</filter-name>
<filter-class>com.qfedu.web.AutherFIlter</filter-class>
</filter>
<filter-mapping>
<filter-name>auther</filter-name>
<url-pattern>/main/*</url-pattern>
</filter-mapping>
限制转发的和包含的形式也要通过过滤器
重要的标签:dispatcher
<filter>
<filter-name>two</filter-name><filter-class>com.qfedu.web.TwoFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>two</filter-name>
<url-pattern>/index.jsp</url-pattern>
<!--dispatcher默认值是REQUEST -->
<!--REQUEST是对一个正常的直接请求的方式进行拦截 -->
<dispatcher>REQUEST</dispatcher>
<!-- 添加FORWARD之后,以转发的方式进入资源也会被过滤 -->
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
关于获取ServletContext对象
1.在javax.servlet.Filter中直接获取
ServletContext context = config.getServletContext();
2.在HttpServlet中直接获取
this.getServletContext()
3.在其他方法中,通过HttpRequest获得
request.getSession().getServletContext();
注意request也有getServletContext();方法。这个方法在tomcat7以上可以使用,7以下的会报错