热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

day036过滤器filter

1案例1-自动登录1.1需求及流程介绍当用户直接访问登录后的页面(例如:购物车页面,订单页面等)直接显示出上一次登录的用户对象,这个功能就是自动登录的功能。如果用户在上一次登录的时


1案例1-自动登录

1.1 需求及流程介绍

当用户直接访问登录后的页面(例如:购物车页面,订单页面等)直接显示出上一次登录的用户对象,这个功能就是自动登录的功能。如果用户在上一次登录的时候,没有勾选自动登录,那么用户直接访问登录后的页面时,不显示用户是谁,加购物车,提交订单等都需要让用户先登录。

(简单说就是跟jd一样。今天只做前一句话,后一句话是权限控制,是后面的内容。)

 

用户自动登录的流程介绍.png


1.2 技术分析

1:可以使用会话技术让服务器知道浏览器发送的多次请求。

2:需要使用过滤器技术,对用户发送的每一次请求都先进行过滤,过滤后,才让用户执行真正的资源。


1.3 过滤器filter概述

过滤器就是运行在服务器最前端的java小程序。

servlet,filter,listener合称为服务器的三大组件,都是被tomcat服务器创建,被服务调用。

servlet与filter的区别:

0:servlet能做的filter一定能做,filter能做的servlet不一定能做。

1:servlet通常用于专一的请求处理,而filter通常用于通用的请求处理;

2:filter一定优先于servlet执行;

进servlet之前要经过filter,从servlet出去的时候也要经过filter。


1.4 过滤器filter的应用场景

1:网站所有请求的中文参数乱码和响应乱码处理。

2:网站访问权限控制。

3:自动登录。

4:敏感字过滤。


1.5 过滤器filter的编写步骤

过滤器的英文名:filter,是javaEE定义的一个接口。

程序员只需实现filter接口,编写相应的方法即可。

image.png

image.png

image.png

关于filter接口中的doFilter方法的3个参数:

ServletRequest类型的参数:代表的是请求对象。

ServletResponse类型的参数:代表的是响应对象。

FilterChain类型的参数:代表的是用于放行的对象。(如果不放行,那么浏览器请求的资源将得不到任何响应)


1.6 自动登录案例的实现

1:案例环境搭建。(数据库创建,静态页面复制,jar包选择,工具类复制)

2:编写3层包结构。

3:将login.html文件修改成login.jsp文件。

4:编写LoginServlet,完成用户完整的登录流程,当用户登陆成功的时候需要将用户对象保存到session中。

5:编写service和dao。

6:修改loginServlet,当用户登录成功的时候,判断用户是否希望帮用户完成自动登录的动作。

如果希望,则创建一个COOKIE对象,并保存用户名和密码为7天

如果不希望,立刻删除原来的COOKIE。

7:编写一个过滤器,在过滤器中获取COOKIE,并使用COOKIE中的用户名和密码查询数据库,如果能查到则帮用户把用户对象保存到session中。

 

注意:

所谓的登录就是session中有用户对象。

部分参考代码:

说明:

页面里

用户名标签处:name="username"

密码标签处:name="password"

是否自动登录勾选选项处标签:name="autoLogin" value="ok"

 

 

过滤器AutoLoginFilter.java:

package com.itheima.anli00_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.COOKIE;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.itheima.anli02_service.UserService;
import com.itheima.anli04_domain.User;
/**
* 完成自动登录的filter
*/
public class AutoLoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/*
* 思路:
*
* 1:判断session中是不是已经拥有了user对象,如果有,则证明用户已经登录了,可以直接放行,否则继续判断下一步;
* 2:获取浏览器携带的所有COOKIE,并查找出名字为auto的COOKIE;如果没有COOKIE,直接放行,否则继续下一步;
* 3:获取COOKIE中的用户名和密码查询数据库;如果查询成功,则保存到seesion中,如果没查到,直接放行;
*
*/

HttpServletRequest r = (HttpServletRequest)request;
HttpSession se = r.getSession();
Object user = se.getAttribute("user");
if(user==null){
//需要继续下一步
COOKIE[] cs = r.getCOOKIEs();
if(cs!=null){
//说明有一部分COOKIE
COOKIE c=null;//准备使用c保存我们想要的COOKIE对象
for (COOKIE COOKIE : cs) {
if(COOKIE.getName().equals("auto")){
c=COOKIE;
}
}
//判断有没有找到COOKIE
if(c!=null){
String value = c.getValue();
String[] split = value.split("");
UserService us = new UserService();
User u2 = us.findUserByUsernameAndPassword(split[0],split[1]);
if(u2!=null){
//帮这个用户保存session
se.setAttribute("user",u2);
}
}
}
}
//放行
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}

LoginServlet.java

package com.itheima.anli01_web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.COOKIE;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.itheima.anli02_service.UserService;
import com.itheima.anli04_domain.User;
/**
* 用户登录的servlet
*/
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println(request);
//1:参 调 存 转
String un = request.getParameter("username");
String ps = request.getParameter("password");
String au = request.getParameter("autoLogin");
//2:调用业务层
UserService us = new UserService();
User u = us.findUserByUsernameAndPassword(un,ps);
//3:存,一定要将用户保存到session对象中,
if(u==null){
//说明用户名或密码错误,回到login.jsp,让用户重新登录
request.setAttribute("msg","用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
return;//结束方法
}
//4:说明查到了用户,保存到session中
request.getSession().setAttribute("user", u);
//判断用户是否希望我们完成自动登录功能
COOKIE c = new COOKIE("auto",un+""+ps);
c.setPath("/");
if("ok".equals(au)){
//说明用户希望自动登录,将COOKIE设置为7天
c.setMaxAge(60*60*24*7);
}else{
//说明用户不希望自动登录,将COOKIE设置为0秒
c.setMaxAge(0);
}
response.addCOOKIE(c);
//转发的购物网站,可以让用户去购物了
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

2 filter总结

2.1 Filter的生命周期

从filter创建一直到filter死亡,这个过程就是filter的生命周期。

Filter的生命周期方法有3个:

init()  初始化

doFilter()  执行过滤

destroy ()  死亡

 

doFilter()方法:只要能匹配路径成功一定会执行,即使有多个filter都匹配了路径也会逐个执行。执行顺序仅仅与web.xml中filter-mapping的配置顺序有关,从上至下,逐个执行。

init()方法:随着tomcat启动就会创建filter对象。

destroy()方法:随着tomcat服务器正常停止而死亡。

 


2.2 多个filter顺序问题:

先后顺序仅仅与在web.xml的配置顺序有关。

filter.png


2.4 FilterConfig对象(了解)

在web.xml中的filter标签中配置init-param属性和属性值时,可以使用FilterConfig对象,获取这些初始化配置参数。

例如:


AutoLoginFilter
AutoLoginFilter
com.itheima.anli00_filter.AutoLoginFilter

aaa

111

javaee的api中有。

常用API:

getInitParameter(属性名);


2.5 关于filter中的url-pattern的配置

在filter中有3种配置:

1:完全匹配    /xxx

2:目录匹配(通配符匹配)   /*       (用的最多)

3:后缀名匹配   *.xxx                        (偶尔使用)

注意:

三种匹配方式不分优先级,只要与路径匹配成功,都会执行,执行顺序仅与web.xml中的配置顺序有关。


2.6 关于filter的拦截方式问题

在filter-mapping中,也可以不使用url-pattern。

使用servlet-name标签替代(了解,不常用)

例如:

 image.png

关于过滤的方式:

 image.png


3 案例3-中文编码过滤器

3.1 需求

当用户访问工程中的任意一个servlet的时候,在servlet中无需再处理中文参数,也无需处理中文响应,都能保证参数和响应数据的正常。(不能乱码)


3.2 技术分析

在servlet中获取参数的方法有3个,分别是:getParameter   getParameterValues    getParameterMap

只要对这3个方法进行增强,即可实现中文参数乱码问题的结果。

响应的时候,只需在调用getWriter或getOutputStream之前,设置响应的Content-Type头信息即可。

使用过滤器就能完成这个事情。


3.3 增强一个类的方法的技术

方式1:继承,重写方法。

缺点:

子类与父类完全绑在了一起,耦合度太高,代码不灵活。(此案例中和tomcat耦合度太高,换个服务器不用tomcat了直接就不好使了)

好处:

简单,好写,快捷。

方式2:装饰者模式

(ps:关于各种各样的设计模式,不管是什么设计模式,都是在抽取工具类的时候才会用)

装饰者模式是指A类与B类是兄弟类,将来面向接口开发的时候,使用A类中的方法,替代B类中的方法,那么此时就可以称为A装饰了B。A就是装饰者,B就是被装饰者。

 

好处:

代码灵活度相对高,只要不更换接口,子类可以替换。

使用前提:

在装饰者中,必须能使用被装饰者的对象,且需要与被装饰者实现相同的接口。

代码步骤:

1:编写一个类,实现与被装饰者相同的接口。(成为兄弟)

2:在类中定义一个接口类型的成员变量用于保存被装饰者对象。

3:编写增强后的方法即可。(增强方法)

本案例中由于直接使用HttpServletRequest接口,需要重写的方法太多,因此选择继承HttpServletRequestWrapper类来与HttpServletRequest接口产生关系。


3.4 过滤器代码实现:

package com.itheima.anli00_filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Set;
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.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
/**
* 我们自己采用装饰者模式,对reqeust对象进行增强的工具类
*/
public class MyEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//1:将request和response转成子接口类型
HttpServletRequest r = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
//2:获取请求方式,如果是get请求,则使用装饰者模式解决乱码,如果是post请求,则直接面向原始的request对象,调用setCharacterEncoding方法解决乱码
String method = r.getMethod();
//3:先解决响应乱码问题
res.setContentType("text/html;charset=utf-8");
if("GET".equalsIgnoreCase(method)){
//说明需要使用装饰者
MyRequest z=new MyRequest(r);
//放行,传递装饰后的对象
chain.doFilter(z, res);
}else{
//可以直接解决
r.setCharacterEncoding("utf-8");
chain.doFilter(r, res);
}
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
class MyRequest extends HttpServletRequestWrapper{
//定义一个接口类型的成员变量,用于保存被装饰的对象
private HttpServletRequest request ;
//为了解决多次调用方法的时候,第一次不乱,之后反而乱码的问题,我们需要定义一个flag,让转换的过程仅执行一次
private boolean flag = true;//默认可以进行转换
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
//增强方法;
//1:增强getParameterMap
public Map getParameterMap() {
//1:先使用request获取原始的浏览器传递过来的参数
Map map = request.getParameterMap();
//2:此时如果map中有中文参数,一定是乱码的!!! 仅考虑get请求,post请求直接面向原始对象解决即可
if(flag){
Set set = map.keySet();
for (String key : set) {
String[] vs = map.get(key);
//对数组中的参数进行处理,处理后需要将参数重新保存回数组
for(int i=0;i //只要对数组的每一个元素进行了修改,那么map中的数组中的元素自然就跟着变化了(已经解决中文乱码了)
try {
vs[i]=new String(vs[i].getBytes("iso8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
//修改flag为false
flag = false;
}
//返回已经解决了乱码的map
return map;
}
//重写getParameterValues方法,这个方法中的数据,都可以直接从map中获取,因为map已经解决了乱码
@Override
public String[] getParameterValues(String name) {
return getParameterMap().get(name);
}
@Override
public String getParameter(String name) {
String[] vs = getParameterValues(name);
if(vs==null){
return "";
}
return vs[0];
}
}

 



推荐阅读
  • 本文讲述了一位80后的普通男性程序员,尽管没有高学历,但通过不断的努力和学习,在IT行业中逐渐找到了自己的位置。从最初的仓库管理员到现在的多技能开发者,他的职业生涯充满了挑战与机遇。 ... [详细]
  • 阿里面试题解析:分库分表后的无限扩容瓶颈与解决方案
    本文探讨了在分布式系统中,分库分表后的无限扩容问题及其解决方案。通过分析不同阶段的服务架构演变,提出了单元化作为解决数据库连接数过多的有效方法。 ... [详细]
  • 本文详细介绍如何在忘记MySQL服务器密码的情况下进行密码重置,包括具体的步骤和注意事项。 ... [详细]
  • 小程序的授权和登陆
    小程序的授权和登陆 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 触发器的稳态数量分析及其应用价值
    本文对数据库中的SQL触发器进行了稳态数量的详细分析,探讨了其在实际应用中的重要价值。通过研究触发器在不同场景下的表现,揭示了其在数据完整性和业务逻辑自动化方面的关键作用。此外,还介绍了如何在Ubuntu 22.04环境下配置和使用触发器,以及在Tomcat和SQLite等平台上的具体实现方法。 ... [详细]
  • PHP自学必备:从零开始的准备工作与工具选择 ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • 周排行与月排行榜开发总结
    本文详细介绍了如何在PHP中实现周排行和月排行榜的开发,包括数据库设计、数据记录和查询方法。涉及的知识点包括MySQL的GROUP BY、WEEK和MONTH函数。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • 本文介绍了如何利用HTTP隧道技术在受限网络环境中绕过IDS和防火墙等安全设备,实现RDP端口的暴力破解攻击。文章详细描述了部署过程、攻击实施及流量分析,旨在提升网络安全意识。 ... [详细]
  • 本文对SQL Server系统进行了基本概述,并深入解析了其核心功能。SQL Server不仅提供了强大的数据存储和管理能力,还支持复杂的查询操作和事务处理。通过MyEclipse、SQL Server和Tomcat的集成开发环境,可以高效地构建银行转账系统。在实现过程中,需要确保表单参数与后台代码中的属性值一致,同时在Servlet中处理用户登录验证,以确保系统的安全性和可靠性。 ... [详细]
  • 如何使用 `org.apache.tomcat.websocket.server.WsServerContainer.findMapping()` 方法及其代码示例解析 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
author-avatar
豆伊一
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有