北京行------java Serlvet Filter 深入理解

day17
Servlet Filter 过滤器

day18
Servlet Listener 和 在线支付

day19
JavaMail

day20
文件上传和下载

JavaEE Servlet规范 描述三种技术 Servlet Filter Listener  都是一个规范的
Servlet 技术 生成动态web资源


Filter 技术 对服务器web资源进行拦截(权限控制)
* Filter 对目标资源拦截,拦截HTTP请求和HTTP响应
* Filter 拦截本质上拦截url访问

Filter接口中定义了三个方法
init 初始化
doFilter 执行过滤
destroy 销毁

* Filter的doFilter方法中,传入FilterChain参数,FilterChain 请求调用链,提供doFilter用于执行调用
链下一个资源

编写Servlet步骤
1、继承HttpServlet
2、配置web.xml Servlet虚拟路径
3、覆盖doGet 和 doPost


编写第一个Filter
1、创建hello.jsp ---- http://localhost/day17/hello.jsp
2、编写类 实现Filter 接口 (实现Filter接口 init doFilter destroy )
3、在web.xml中 注册过滤器,配置Filter拦截哪个web资源

在启动服务器时,Filter对象被创建,执行过滤器init 方法

servlet是在第一次访问时才创建
配置拦截后,访问hello.jsp --- 过滤器中doFilter方法获得执行(每请求一次,doFilter 过滤一次)
* 没有配置过滤器之前,直接访问hello.jsp,当配置过滤器后,过滤器先于hello.jsp执行 ----- 此时
Filter1和hello.jsp组成 请求调用链FilterChain 《它代表的是一个请求调用链》
* 拦截目标资源后,如果想目标资源执行: chain.doFilter ;如果不执行chain.doFilter 目标资源不会得
到执行

 

destroy方法和Servlet的destroy 一样,在正常关闭服务器情况下执行

  <filter>
      <filter-name>MyFilter</filter-name>
      <filter-class>MyFilter1</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping>
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 MyFilter1 implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        System.out.println("Filter 销毁");
    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        // TODO Auto-generated method stub
        System.out.println("我执行了。。。。");
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        System.out.println("我启动了");
    }

}

 

* 对同一web资源配置多个过滤器
当配置多个Filter 拦截hello.jsp 组成新的请求调用链 Filter1 --- Filter2 --- hello.jsp
过滤器链会根据mapping 的顺序组成 <filter-mapping> 顺序调用过滤器执行

 

Filter生命周期三个方法:init doFilter destroy
1、init初始化 ---- 在服务器启动时执行
2、doFilter 执行过滤 ---- 访问目标时,拦截过滤执行,每次请求执行一次
3、destroy 销毁过滤器对象 ----- 在服务器正常关闭时调用

FileConfig 作用和ServletConfig 类似---- 为过滤器提供初始化参数
*String getInitParameter(String name) 获得初始化信息
*public ServletContext getServletContext() 获得ServletContext对象 保存全局数据、读取web资源文件(获取文件路径)

读取web资源,必须要获得绝对磁盘路径

配置filter-mapping
1、对一个web资源可以配置多个过滤器
2、一个过滤器可以用来过滤多个web 资源
* 在filter-mapping中存在 <servlet-name> 过滤Servlet时,可以通过url 和 name两种配置方式
<url-pattern>/hello</url-pattern>
<servlet-name>HelloServlet</servlet-name>
3、关于url-pattern 写法和Servlet相同 有三种 完全匹配、目录匹配、扩展名匹配

<dispatcher> 标签及意义
配置在什么情况下、在什么调用方式下拦截目标资源
request,forward、include、error 四种方式,服务器调用资源方式
* 默认dispatcher值是request (请求时调用)
request ---- 在请求时过滤
forward ---- 在转发时过滤
include ---- 在包含时过滤
error --- 在错误页面跳转时过滤

如果想让过滤器执行,必须满足过滤方式 !!!! 如果forward、include 、error跳转时执行过滤 必须配
置 dispatcher

案例一:关于编码集统一处理
功能描述:编写 input.jsp 提供输入姓名表单,在Servlet获得表单数据,将数据打印页面上
分析:过滤器在目标资源之前执行 ,过滤器拦截多个目标资源,多个目标资源相同代码,抽取过滤器中
----- 经常写代码放入过滤器

request.setCharacterEncoding("utf-8");// 解决请求post乱码
response.setContentType("text/html;charset=utf-8"); // 响应乱码
将以上代码放入EncodingFilter,配置url 为/* 对全站web资源进行编码集设置

复习点:get乱码解决 第一种 配置tomcat server.xml URIEncoding="utf-8" 第二种 new String
(xxx.getBytes("ISO-8859-1"),"utf-8");
* 重写getParameter 编写通用解决get乱码程序
* 阅读扩展资料 解决get post 全局乱码过滤器

 login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/FilterTest/charfilter" method="post">
    姓名:<input type="text" name="username">
    密码:<input type="text" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>

TestFilter.java

package cn.binbin;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestFilter extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.println(username);
        response.getWriter().write(username);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

CharFilter.java

package cn.binbin.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 CharFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

}

web.xml

   <filter>
           <filter-name>CharFilter</filter-name>
           <filter-class>cn.binbin.filter.CharFilter</filter-class>
   </filter>

<filter-mapping>
    <filter-name>CharFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

案例二:禁用缓存过滤器

分析:在web开发中,存在很多动态web资源,经常需要更新,为了保证客户端第一时间获得更新后结果,禁
止动态web资源缓存
禁止缓存三个头信息
cache-control : no-cache
expires : -1 ---- 日期
pragma : no-cache

response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
response.setHeader("Pragma", "no-cache");

* 禁用缓存公共代码放入过滤器中 ------ NoCacheFilter 禁止动态资源缓存

这个还是比较简单的,就是在Filter中设置几个头信息

 

案例三:对于图片一系列资源,不经常发生变动 ----- 图片缓存过滤器
* 虽然tomcat服务器内部 对静态资源有一个缓存策略,但是客户端仍然需要与服务器进行通信,通信性能损

* 如果一些图片 永远不变,通过Expires 字段,设置图片 缓存时间 (当缓存时间没有过期之前,客户端方
位资源 不会与服务器进行通信)

Expires 对于经常不变文件,是一个比tomcat默认缓存策略更优 解决方案!!!

-----------------------------------------------------------------------------------------------
---------------------------------
案例四:自动登陆过滤器
功能:第一次登陆时,勾选自动登陆,关闭浏览器,再次打开,系统会自动进行用户已经登陆状态

登陆功能
create table user(
id int primary key auto_increment,
username varchar(40),
password varchar(40),
role varchar(40)
);

insert into user values(null,'aaa','111','admin');
insert into user values(null,'bbb','111','user');
insert into user values(null,'ccc','111','user');

* 复制mysql驱动、c3p0、dbutils 到WEB-INF/lib 下
* 复制JDBCUtils 工具类 和c3p0-config.xml

转发和重定向使用
1、使用转发,通过request.setAttribute 传递数据给 页面,路径不要写/工程名 ;
2、使用重定向,不能用request传递数据,路径 要写 /工程名

AutoLoginFilter 在什么情况下需要自动登陆 ??
1、当前用户必须未登陆
2、存在自动登陆cookie信息

* 自动登陆过滤器,过滤页面一定不包括登陆和注册 页面

自动登陆案例问题:
1、 如果用户名中文怎么办?
insert into user values(null,'小红','123','user');
解决方案:保存cookie时进行手动编码 URL编码
生成cookie 时 new Cookie(URLEncoder.encode(用户名,"utf-8")); ------ LoginServlet
读取cookie时, 对用户进行解码 URLDecoder.decode(用户名,"utf-8"); ---- AutoLoginFilter

2、 中文名和密码安全问题
* cookie 是一个文本类型文件,内容非常容易泄露
实际开发中数据库中密码和cookie中密码 都应该 加密后保存 ---- 单向加密算法 MD5
* MySQL 提供md5 方法进行加密
将数据进行md5 加密
update user set password = md5(password) ;

MD5 破解 ----- 多对一映射算法 (运行两个不同明文 产生相同密文 概率很低) ---- 王小云 并没有提
供解密算法,提供一套提高碰撞几率算法
* http://www.cmd5.com/

Base64 编解码技术,用于加密网络传输中安全内容 ---- 例如:迅雷下载地址
* 很多协议内容传输都采用BASE64 编码

案例五:关于URL级别权限控制
一个软件系统功能非常多,将功能进行分类(根据用户角色),将不同功能放入不同url 目录中 ,对目录级
别进行url 权限控制

/public/ 代表游客可以访问 : 用户注册、用户登录
/user/ 代表普通用户可以访问: 购买商品,查看购物车,订单支付
/admin 代表超级管理员可以访问:查看商品销售情况,添加商品

建立JSP,在index.jsp提供对八个功能jsp访问 链接
编写登陆功能
仍然使用 day17 数据库 下 user 表
* 权限控制时,登陆功能游客可以访问 ----- 已经将login.jsp 放入public 但是 LoginServlet 也是登陆
程序 也路径放入public
* LoginServlet 配置url-pattern 必须为/public/login

编写PrivilegeFilter 对资源进行全局权限控制

* 重点:
1、 获得访问资源路径
String path = httpServletRequest.getRequestURI().substring(httpServletRequest.getContextPath
().length());
2、 判断当前用户是否登陆
User user = (User) httpServletRequest.getSession().getAttribute("user");
if (user == null) {
// 未登陆
} else {
// 已经登陆
}
* 过滤掉未登录不能访问资源
3、获得用户权限,判断权限可以访问哪些资源 user.getRole()


今天学习重点内容:
1、过滤器原理
2.过滤器5个案例
案例一、案例二、案例三 重点原理 --- 代码很少
案例四 自动登陆 (原理) --- 会写
案例五 URL级别权限控制 (重点!!!!!!)

posted @ 2013-04-26 19:08  蓝冰悠见  阅读(294)  评论(0编辑  收藏  举报