java_web_filter
1. Filter(过滤器)是什么?
过滤源 过滤规则 过滤结果
web过滤器是什么?
web过滤器过滤的是用户请求.不能直接处理请求.只是用来做辅助性的工作.在无登录情况下,购买商品或者观看课程,跳转到登录页面,或者找不到请求url时统一跳转到404页面.
定义:是一个服务器端的组件,截取用户的请求和响应信息,并对这些信息进行过滤.(有自己的过滤规则).
工作原理?
web容器在启动的时候,就已经加载过滤器了.当用户发出请求并不是直接到web资源的.是到了过滤器的,这个时候过滤器根据过滤规则判断请求是否符合过滤规则.是(符合),就会把用户的请求发送给web资源,web服务处理完请求,响应到过滤器,web过滤器再将资源响应给发送的用户.
生命周期?
实例化:通过web.xml中配置,这样容器在一启动的时候,就加载了过滤器了.就是实例化了过滤器.只会实例化一次.
初始化:加载一些初始化信息(调用init()方法.进行一些初始化的相关操作,初始化也是只执行一次.)
过滤(方法):针对过滤器中的doFilter()方法,它是能执行n次的,过滤器只要捕获它的请求,都会执行这个doFilter方法.
销毁:调用destroy()方法.在web容器关闭的时候就会销毁过滤器.
类型?
第一过滤器案例:
FirstFilter.java (com.imooc.filter)
//是过滤器的初始化方法,web容器创建过滤器实例后将调用这个方法,这个方法可以读取web.xml中的过滤器的参数.
init(FilterConfig filterConfig) throwsServletException{
}
//是完成实际的过滤操作,是过滤器的核心方法.当用户访问与这个过滤器关联的url的时候,web容器将先调用过滤器的doFilter方法,
FilterChain参数可以调用chain.doFilter()方法,将请求传给下一个过滤器(或目标资源),或利用转发,重定向将请求转发到其他资源.
doFilter(ServletRequestrequest,ServletResponse response,FilterChain chain){
}
//web容器在销毁过滤器实例前调用该方法,在这个方法中,可以释放过滤器占用的资源(大多数情况下用不到)
destrory()
配置过滤器
<url-pattern>url:当用户请求的url和指定的url匹配的,才触发过滤器工作</ url-pattern >
?问题:
1.过滤器是否能改变用户请求的web资源(也就是是否能改变用户请求的url路径)
2.过滤器能否直接返回数据,能不能直接处理用户请求?
多个过滤器是什么样子?多个过滤器针对同一个请求,过滤器的执行顺序会是什么样子?
过滤器链:
如果url拦截的地址不同,就谈不到什么过滤器链了.
如果url-pattern的拦截地址相同:
针对一个用户请求,我们找到多个匹配的过滤器,就形成了过滤器链.会按照web.xml中过滤器定义的先后顺序执行.
过滤器的分类:
servlet2.5中分四种类别:
request:用户直接访问页面时,web容器将会调用过滤器.
forward: 目标资源是通过RequestDispatcher的forward访问时,该过滤器将被调用.
include:过滤器也被调用.
error:目标资源是通过声明式异常处理机制调用时,过滤器将被调用.
ErrorFilter.java
async:支持异步处理
如果其中一个过滤器doFilter中调整到一个servlet,如果servlet中有个业务方法执行的时间很长,这个时候,过滤器就会一直等待这个servlet完成.响应不出界面,给用户体验就会很差.3.0以后呢,支持异步处理,不管servlet执行完没有都会一直往下走.用户会看到已经执行完了,可以让用户看到他想要的结果了.
WebFilter:用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器.
servlet3.0
@WebFilter(filterName="AsynFilter",asyncSupported=true,value={"/servlet/AsynServlet"},dispatcherTypes={DispatcherType.REQUEST,DispatcherType.ASYNC})
public class AsynFilter implements Filter {
@Override
publicvoid destroy() {
}
@Override
publicvoid 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
publicvoid init(FilterConfig arg0) throws ServletException {
}
}
public void doGet(HttpServletRequestrequest, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet执行开始时间:"+newDate());
AsyncContext context= request.startAsync();
new Thread(newExecutor(context)).start();
System.out.println("Servlet执行结束时间:"+new Date());
}
publicclass Executor implements Runnable{
privateAsyncContext context;
publicExecutor(AsyncContext context ) {
this.context= context;
}
@Override
publicvoid run() {
//执行相关复杂业务
try{
Thread.sleep(1000*10);
// context.getRequest();
// context.getResponse();
System.out.println("业务执行完成时间:"+new Date());
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
登录认证及编码转换实战?
1. 判断用户是否符合登录认证的条件.
2. 对编码字符集进行转换,以便在开发中不会出现乱码
3. 防止攻击(对登录的参数进行判别)
4. 对response进行后处理,转换它的格式输出
5. 做压缩操作,对内容进行加密操作.
<body>
<form action="<%=request.getContextPath()%>/servlet/LoginServlet" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
Stringusername = request.getParameter("username");
Stringpassword = request.getParameter("password");
System.out.println(username);
if("admin".equals(username)&& "admin".equals(password)){
//校验通过
HttpSessionsession = request.getSession();
session.setAttribute("username",username);
response.sendRedirect(request.getContextPath()+"/sucess.jsp");
}else{
//校验失败
response.sendRedirect(request.getContextPath()+"/fail.jsp");
}
}
<body>
登录成功,欢迎您,${username}
</body>
<body>
登录失败,请检查用户名和密码!
</body>
以上直接输入url是可以访问到页面的(因为没有放到WEB-INF下)
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.imooc.filter.LoginFilter</filter-class>
<init-param>
<param-name>noLoginPaths</param-name>
<param-value>login.jsp;fail.jsp;LoginServlet</param-value>
</init-param>
<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>
public void doFilter(ServletRequest arg0,ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
HttpServletRequestrequest = (HttpServletRequest) arg0;
HttpServletResponseresponse = (HttpServletResponse) arg1;
HttpSessionsession = request.getSession();
StringnoLoginPaths = config.getInitParameter("noLoginPaths");
Stringcharset = config.getInitParameter("charset");
if(charset==null){
charset= "UTF-8";
}
request.setCharacterEncoding(charset);
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;
}
}
}
private FilterConfig config;
@Override
publicvoid init(FilterConfig arg0) throws ServletException {
config= arg0;
}
if(session.getAttribute("username")!=null){
arg2.doFilter(arg0,arg1);
}else{
response.sendRedirect("login.jsp");
}
}
编码转换案例:
1. 修改tomcat字符集
2. 强制转换
3. filter编码转换
String charset = config.getInitParameter("charset");
if(charset==null){
charset ="UTF-8";
}
request.setCharacterEncoding(charset);