今天内容:
1.Servlet最激动人心三大技术:Servlet,Filter,Listener
2.过滤器(Filter):Servlet三大技术之一,在服务器可以管理所有web资源,本质特殊java类.
WEB开发人员通过Filter技术,对web服务器管理 的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊 的功能。
过滤器的作用:实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
3.过滤器工作原理:
4.手动写过滤类:
4.1:先创建一个Java类,实现javax.servlet.Filter接口;
4.2:实现接口中init(),doFilter(),destroy();
4.3:在web.xml中注册过滤器
注意:配置版的过滤器在过滤器链中顺序由注册顺序.
eg:<!--注册过滤器-->
<filter>
<filter-name>FirstFilter</filter-name><!--过滤器注册名-->
<filter-class>com.qf.day46.filter.FirstFilter</filter-class><!--过滤器全限制类名:包名+类名-->
</filter>
<!--配置过滤过滤请求的路径-->
<filter-mapping>
<filter-name>FirstFilter</filter-name><!--过滤器的注册名,与上面注册名相同-->
<url-pattern>/*</url-pattern><!--过滤所有请求-->
</filter-mapping>
//等同于用注解在类名上注册
@WebFilter(filterName = "SecondFilter",value = "/*")//配置注册信息和映射请求
简写为:@WebFilter("/*")
注意:注解版的过滤器在过滤器链中顺序由注册过滤器名称决定.
5.过滤器的生命周期:
当项目发布时,由服务器容器调用构造方法,实例化过滤器,再由服务器容器通
过过滤 实例调用init()初始过滤器,当客户端发送请求到服务器时,由服务器容器通
过过滤 器实例调用doFilter方法,再将请求传到Servlet中处理,Servlet处理完请
求响应 信息,由服务器容器通过过滤器实例调用doFilter方法,再将响应信息传到客
户端. 当web项目停止发布时就调由服务器容器通过过滤器实例调用destroy()销毁
过滤器 实例.(与web项目同生共死)
6.Servlet3.0之后,注解的过滤器:在过滤类上面配置注解@WebFilter,可配置属性
7.字符编码过滤器:
原来实现: 请求和响应对象是在Servlet中处理编码
现在实现: 在过滤器中处理编码,将处理好编码的请求和响应对象传Servlet中,Servlet就 不会再处理编码
实现思路: 声明一个字符编码过滤器,在过滤器中将响应的编码和请求编码提前编码后,后 面在将请求和响应对象传Servlet中就不用处理编码.注意,因为get请求的编码无法统一在类中设置,所以就想重写获得请求中数据的方法.因为要重写获得请求中数据的方法,所以请求对象要用装饰都模式.
eg:/**
* 字符编码过滤器
*/
@WebFilter("/*")
public class EncoddingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
/**
* 过滤方法
* @param request
* @param response
* @param chain
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//统一处理响应编码
response.setCharacterEncoding("utf-8");
/*处理请求编码*/
//将请求对象转换为HttpServletRequest
HttpServletRequest request2=(HttpServletRequest)request;
//获得请求方法类型
if ("GET".equalsIgnoreCase(request2.getMethod())){
//创建请求的装饰者对象,将原来的请求对象作为构造方法的参数
MyRequest mr=new MyRequest(request2);
chain.doFilter(mr, response);
}else if("POST".equals(request2.getMethod())){//post请求
request2.setCharacterEncoding("utf-8");
chain.doFilter(request2, response);
}
}
/**
* 装饰者请求类(成员内部类)
*/
public class MyRequest extends HttpServletRequestWrapper{
public HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
/**
* 重写获得单个请求值的方法
* @param name
* @return String
*/
@Override
public String getParameter(String name) {
//获得请求中值
String value=super.getParameter(name);
try {
if(value!=null&&!value.equals("")){
//重写编码
value=new String(value.getBytes("ISO-8859-1"),"utf-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
}
/**
* 重写获得请求中一组数据值的方法
* @param name
* @return String
*/
@Override
public String[] getParameterValues(String name) {
//获得请求中一组数据值
String[] values=super.getParameterValues(name);
//将数据值一一编码
if (values!=null||values.length!=0){
for (int i=0;i<values.length;i++){
try {
values[i]=new String(values[i].getBytes("ISO-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return values;
}
/**
* 重写获得请求中所有值的方法
* @return String
*/
@Override
public Map<String, String[]> getParameterMap() {
Map<String,String[]> hmap1=super.getParameterMap();
//处理请求中每个数据的编码
for (String key:hmap1.keySet()){
//通过key得到value值
String[] values=hmap1.get(key);
//将数据值一一编码
if (values!=null||values.length!=0){
for (int i=0;i<values.length;i++){
try {
values[i]=new String(values[i].getBytes("ISO-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
return hmap1;
}
}
}
8.权限验证过滤器
原来效果:无论用户是否登录都可以直接访问首页,或其他页面.
实现效果:只有登录过的用户才能访问首页和其他页面,没有登录过的用户,如果直接访问首页或其他页面,让其3秒跳转到登录页并提示你还没有登录,无法作其他操作.
实现原理:因为每次请求时都要先经过过滤器再经过Servlet,所以就想一个权限验证过滤器,在这个过滤器中作判断,判断只有登录过的用户才放行调用
chain.doFilter (mr, response);,否则让用户跳转到登录页面.
就超市系统来说:只有登录的页面,登录的请求方法,已经登录过的用户,css,js,img放行
eg:/**
* 权限验证过滤器
*/
@WebFilter("/*")
public class AccessFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//将请求和响应对象转换为子类对象
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse)resp;
//获得session登录的用户信息
Object ob=request.getSession().getAttribute("u");
//获得请求的uri
String uri=request.getRequestURI();
//获得请求的方法名
String method=request.getParameter("method");
//如果是默认起始页,/web_market/login.jsp,登录请求,已经登录过的用户也要放行
if("/web_market/".equals(uri)||"/web_market/login.jsp".equals(uri)||"login".equals(method)||ob!=null){
//放行,继续执行请求
chain.doFilter(request, response);
}else{//没登录,无法处理后面的请求,就要三秒跳转到登录页面
//设置响应的内容类型
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("你还没有登录,无法进行其他操作,3秒后跳转到登录页面");
response.setHeader("refresh","3;url=login.jsp");
}
}
public void init(FilterConfig config) throws ServletException {
}
}