Java Web开发技术应用——过滤器,java技术应用
Java Web开发技术应用——过滤器,java技术应用
文章目录
- Java Web开发技术应用——过滤器
- 1.过滤器简介
- 2.[Java Web] 过滤器的工作原理和生命周期
- 3.[Java Web] 第一个过滤器案例
- 4.[Java Web] 过滤链
- 5.[Java Web] 过滤器的分类1
- 6.[Java Web] 过滤器的分类2
- 7.[Java Web] 过滤器的分类3
- 8. 登录案例和编码转换案例
Java Web开发技术应用——过滤器
1.过滤器简介
过滤器定义:
过滤器是一个服务器端的组件,它可以截取用户端的请求与相应信息,并对这些信息过滤
2.[Java Web] 过滤器的工作原理和生命周期
过滤器的工作原理:
在没有过滤器的时候,用户发出请求,直接访问我们web资源,假如说存在过滤器,直接访问是不行的。
过滤器是在web应用程序启动的时候就加载了,用户发送请求到过滤器,过滤器来判断用户请求是否合法,之后将请求发送至web资源,资源响应之后又发送给过滤器,再从过滤器将web资源的响应发送给客户
过滤器生命周期
实例化(web.xml配置)只执行一次
初始化(init())只执行一次
过滤(doFilter())获取请求均会执行该方法
销毁(destroy())在web容器关闭时会执行销毁
3.[Java Web] 第一个过滤器案例
这里创建web项目,src文件夹下创建包,接口Filter,会自动生成:
init()方法,web容器在创建过滤器的实例后会进行初始化,调用这个方法,该方法可以读取web.xml文件中过滤器的参数;
doFilter()方法,进行实际的过滤操作,这是过滤器的核心方法,当用户请求访问与过滤器关联的URL时,web容器将先调用doFilter方法。FileChain参数可以调用chain.doFilter方法,将请求传给下一个过滤器或目标资源,或利用转发重定向将请求转发到其他资源
destroy()方法,销毁过滤器前会调用该方法,释放占用的资源,一般用不到。
如何自动生成web.xml,在web项目生成时最后有一个选项打钩即可。
web.xml配置
只能配置一个
可以配置多个
其中filter标签里的是过滤器类,上面是过滤器名过滤器类,类名需要包含包名也就是完整名称,而init-param是初始化参数信息,可以向浏览器传递零对或者多对参数值。
filter-mapping是过滤器映射,可以设置一个或者多个url地址,dispatcher是过滤器的类型,可以设置过滤什么请求,默认是request。在设置web.xml时,eclipse提供了一个快捷方法,点击design设置,然后选择filter,可以添加一个filter Add new filter或者添加一个filter映射 Add new Filter Mapping,分别设置完成配置,如果过滤所有浏览器则在映射url地址填入“/*”,如果是某些前缀的地址则比如“/index *”之后这样我们第一个过滤器也就配置成功了
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>ImoocFilterOne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.imooc.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
FirstFilter类
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class FirstFilter implements Filter {
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO 自动生成的方法存根
System.out.println("开始?");
arg2.doFilter(arg0, arg1);
System.out.println("结尾");
}
@Override
public void init(FilterConfig arg0) throws ServletException{
System.out.println("init");
}
}
这里有两个问题,过滤器是否能改变用户请求的web资源呢?也就是能否改变用户请求的路径,这个是可以的,不符合要求比如可以跳转到注册界面等等。
过滤器能否直接返回数据呢?能不能处理用户请求,这个是不能的,不是servlet,它可以重定向。
4.[Java Web] 过滤链
这里我们来学习一下,web项目中多个过滤器是如何实现的?多个过滤器对应同一个用户路径执行顺序如何?
首先过滤器是支持多个过滤器的,我们可以声明过滤器1,也可以声明过滤器2,那么每个过滤器都有自己对应的url地址,这里面我们可以用来过滤用户的请求,假如说我们过滤器1和过滤器2没有交集,并不相等。
多个过滤器的情况
1:多个过滤器过滤的URL不同,那么此时的多个过滤器是互不相干的,各过滤各的,互不干扰
2:多个多虑期过滤的URL相同,那么此时的多个过滤器就形成了一个过滤器链,根据在Web.xml文件中配置的声明的顺序来决定,哪个先过滤哪个后过滤
核心方法是 doFilter()方法
第二个过滤器范例,过滤器链
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SecondFilter implements Filter {
@Override
public void destroy() {
System.out.println("结束--secondFilter");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO 自动生成的方法存根
System.out.println("secondFilter--doFilter--start");
arg2.doFilter(arg0, arg1);
System.out.println("secondFilter--doFilter--end");
}
@Override
public void init(FilterConfig arg0) throws ServletException{
System.out.println("初始化---seconFilter");
}
}
控制台输出结果:
调用service之前执行一段代码-doFilter-FirstFilter–start
secondFilter–doFilter–start
处理过程完成
secondFilter–doFilter–end
调用service之后执行一段代码-doFilter-FirstFilter–end
这里可以观察到,首先指定的是第一个过滤器的放行前方法,之后是第二个过滤器的放行前方法,之后到达我们的web资源,也就是index.jsp进行业务处理。之后执行的是第二个过滤器的放行后方法,然后是第一个过滤器的放行后方法
5.[Java Web] 过滤器的分类1
在servlet2.5中过滤器分为4种类别,它包括request、forward、include以及error,首先我们先讲解request这个过滤器的使用,它主要是用户直接访问页面时,Web容器将会调用过滤器。
这里我们先将上节第二个过滤器注释在web.xml中注释掉,下面来增加一点难度,我们再给第一个过滤器增加一个映射main.jsp,然后我们在1过滤器中取消放行方法,直接强行跳转到main.jsp。这里我们思考一下,我们访问index时会执行过滤操作,跳转到main.jsp,同时main.jsp同样也设置了过滤映射,一样会进行过滤操作,而再进行操作时又会进行跳转,这里会出现死循环,下面实际操作来验证一下。
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO 自动生成的方法存根
System.out.println("调用service之前执行一段代码-doFilter-FirstFilter--start");
//arg2.doFilter(arg0, arg1);
HttpServletRequest request=(HttpServletRequest)arg0;
HttpServletResponse response=(HttpServletResponse)arg1;
request.getRequestDispatcher("main.jsp").forward(request,response);
//response.sendRedirect("main.jsp");
System.out.println("调用service之后执行一段代码-doFilter-FirstFilter--end");
}
使用send重定向出现了无限循环,走的是request。也可以理解成它告诉了浏览器我们要访问一个新的地址了。
而使用转发forward结果则是进入main.jsp界面后结束,也就是第二个过滤映射没有起作用,这是重定向和转发的区别,前者url栏已经变成了main.jsp,有一个新的请求在访问,而转发则还是原来的请求,浏览器不关心你到底访问哪个地址,请求转发到了main.jsp,url地址栏不变。这是自己的看法不知道对不对,而后面就将介绍forward类型的过滤器。
forward过滤器,目标资源是通过RequestDispatcher的forward()访问时,该过滤器将被调用。
此时我们修改过滤器类型为forward,然后看一下转发的结果有异常吗
在映射中添加FORWARD
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/main.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
此时又出现了死循环结果
include和jsp同理
request.getRequestDispatcher("main.jsp").include(request,response);
<jsp:forward page="main.jsp"></jsp:forward>
<jsp:include page="main.jsp"></jsp:include>
include过滤器,目标资源是通过RequestDispatcher的include方法()调用时,该过滤器将被调用。
6.[Java Web] 过滤器的分类2
ERROR类过滤器:目标资源是通过声明式异常处理机制调用时,过滤器将被调用。
比如说我们访问一个路径的时候,出现一个错误,那么这个时候系统会给出一个错误提示,那么这个错误给用户之后,用户看不懂这个错误是什么概念,这个时候我们就需要给出一个人性化的提示,下面我们来进行演示。我们将之前案例中的第二个main.jsp映射注释掉,使用重定向mian.jsp。此时我们测试,如果访问mian1.jsp则会出现404报错。这时我们就可以使用error功能了。
在web.xml中添加一个标签
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
有了此标签,如果访问地址是404错误就会直接显示error.jsp
然后我们要用过滤器,应该再添加一个过滤器标签和过滤器类
<filter>
<filter-name>ErrorFilter</filter-name>
<filter-class>com.imooc.filter.ErrorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ErrorFilter</filter-name>
<url-pattern>/error.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
添加一个ErrorFilter类
public class ErrorFilter implements Filter {
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO 自动生成的方法存根
System.out.println("捕捉到异常!");
arg2.doFilter(arg0, arg1);
}
}
这里记得要设置放行就会显示error.jsp页面。
在servlet2.5中是四个选项,REQUEST FORWARD INCLUDE ERROR。在3.0中又添加了一个功能ASYNC,支持异步处理。
在3.0之中,它加入了@WebFilter
@WebFilter这是用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。例如:
@WebFilter(servletNames={"SimpleServlet"},filterName="SimpleFilter")
public class LessThanSixFilter implements Filter{...}
@WebFilter的常用属性
7.[Java Web] 过滤器的分类3
Servlet3里面使用过滤器
这里我们首先来设置一个过滤器
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
@WebFilter(filterName="AsynFilter",value="/asyn.jsp",dispatcherTypes= {
DispatcherType.REQUEST,DispatcherType.ASYNC
})
public class AsynFilter implements Filter {
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO 自动生成的方法存根
System.out.println("start...asynfilter");
//放行
arg2.doFilter(arg0, arg1);
System.out.println("end...asynfilter");
}
}
创建jsp页面后我们发现过滤器有了,但是实际的异步我们这里还没有具体实现,下面开始补充。这里我们创建一个新的包servlet包里建立AsynServlet文件,重写doGet()方法,这个时候我们就需要线程的操作,在线程里模拟异步的操作,创建一个内部线程类
package com.imooc.servlet;
import java.io.IOException;
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 implementation class AsynServlet
*/
public class AsynServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AsynServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("servlet开始时间"+new Date());
AsyncContext context =request.startAsync();// 将context对象传入到run方法里,在执行线程的时候是没办法获取request和response
new Thread(new Executor(context)).start();
System.out.println("servlet结束时间"+new Date());
}
public class Executor implements Runnable{
private AsyncContext context;
public Executor(AsyncContext context) {
this.context=context;
context.getRequest();
context.getResponse();
//可以通过它来获取
}
@Override
public void run() {
// TODO 自动生成的方法存根
try {
Thread.sleep(1000*10);
System.out.println("业务执行完成时间"+new Date());
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Servlet配置文件
<servlet>
<servlet-name>AsynServlet</servlet-name>
<servlet-class>com.imooc.servlet.AsynServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>AsynServlet</servlet-name>
<url-pattern>/servlet/AsynServlet</url-pattern>
</servlet-mapping>
过滤器设置
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
@WebFilter(filterName="AsynFilter",asyncSupported=true,value={"/servlet/AsynServlet"},dispatcherTypes={DispatcherType.REQUEST,DispatcherType.ASYNC})
public class AsynFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
System.out.println("start.....AsynFilter");
arg2.doFilter(arg0, arg1);
System.out.println("end.....AsynFilter");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
执行结果:
start.....AsynFilter
Servlet执行开始时间:Mon Jan 07 15:43:26 CST 2019
Servlet执行结束时间:Mon Jan 07 15:43:26 CST 2019
end.....AsynFilter
业务执行完成时间:Mon Jan 07 15:43:27 CST 2019
最后一条晚了10秒钟,异步。
可以看出,不会等待Servlet里面的异步执行完毕
8. 登录案例和编码转换案例
LoginServlet - 登录成功跳转到sucess.jsp,失败跳转到fail.jsp
package com.imooc.serlvet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet {
/**
* Constructor of the object.
*/
public LoginServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
if("admin".equals(username) && "admin".equals(password)){
//检验通过
HttpSession session = request.getSession();
session.setAttribute("username", username);
response.sendRedirect(request.getContextPath()+"/sucess.jsp");
}else{
//检验失败
response.sendRedirect(request.getContextPath()+"/fail.jsp");
}
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
Servlet配置文件
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.imooc.serlvet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
LoginFilter - 登录过滤
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginFilter implements Filter {
private FilterConfig config;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
HttpSession session = request.getSession();
String noLoginPaths = config.getInitParameter("noLoginPaths");
// request不是UTF-8时设置为UTF-8
String charset = config.getInitParameter("charset");
if(charset==null){
charset = "UTF-8";
}
request.setCharacterEncoding(charset);
// url中包含特定字段不做下面的过滤处理
if(noLoginPaths!=null){
String[] strArray = noLoginPaths.split(";");
for (int i = 0; i < strArray.length; i++) {
if(strArray[i]==null || "".equals(strArray[i]))continue;
if(request.getRequestURI().indexOf(strArray[i])!=-1 ){
arg2.doFilter(arg0, arg1);
return;
}
}
}
if(session.getAttribute("username")!=null){
arg2.doFilter(arg0, arg1);
}else{
response.sendRedirect("login.jsp");
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
config = arg0;
}
}
Filter配置文件
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.imooc.filter.LoginFilter</filter-class>
<!--url中包含下面的字段不进行LoginFilter中下面的过滤处理-->
<init-param>
<param-name>noLoginPaths</param-name>
<param-value>login.jsp;fail.jsp;LoginServlet</param-value>
</init-param>
<!--request不是UTF-8时设置为UTF-8-->
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
相关文章
- 暂无相关文章
用户点评