本帖最后由 森111 于 2019-1-4 10:21 编辑
Filter过滤器的概念一般用于完成通用的操作,如登陆验证,统一编码处理,敏感字符过滤快速入门1.WebFilter注解
配置url-pattern(默认为value)为要拦截的路径
2.web.xml配置
<filter>
<fileter-name>demo1</filter-name>
<filter-class>cn.itcast.web.filter.FliterDemo1</filter-class>
</filter>
<filter-mapping>
<fileter-name>demo1</filter-name>
<url-pattern>cn.itcast.web.filter.FliterDemo1</url-pattern>
</filter-mapping>
!!!注意,这里url-pattern配置的是要拦截的路径
Filter细节浏览器--> servletChian.doFilter()-->Servlet
-->servletChian.doFilter之后的代码-->浏览器1.init():在服务器启动后会创建Filter对象,调用init()方法
2.doFilter():每一次请求拦截资源,执行一次
3.destory():服务器正常关闭,执行一次1./具体资源 (很少使用)
2./user/* 过滤user下的所有资源
3. *.jsp 过滤所有后缀名为jsp的资源
4./* 过滤所有资源1.注解配置
设置dispatcherType属性
- REQUEST:默认值.浏览器直接请求资源
- FORWAR:转发访问资源
- INCLUDE:包含访问资源 (了解)
- ERRO:错误访问资源,Jsp中配置的erroPage (了解)
- ASYNC:异步访问资源(了解)
2.web.xml配置
<filter-mapping>中的<dispatcher></dispatcher>浏览器-->Filter1.filterChain.doFilter()
-->Fileter2.filterChian.doFilter()-->Servlet
-->Fileter2.filterChian.doFilter()之后的代码
-->Fileter1.filterChian.doFilter()之后的代码
-->浏览器1.WebFilter注解
按照字母顺序排序
2.web.xml
按照<filter-mapping>中的顺序
设计模式动态代理概念 1.真实对象:被代理的对象
2.代理对象:代理真实对象的对象
3.代理模式:代理对象代理真实对象,达到增强真实对象功能的目的实现方式 1.静态代理:有一个类文件描述代理模式
2.动态代理:在内存中形成代理类1.代理对象和真实对象实现相同的接口
2.Proxy.newProxyInstance(ClassLoader,Class<?>[],InvocationHandler)来获取一个代理对象
3.使用代理对象来调用方法
4.增强方法1.参数
- Classloader:真实对象.getClass().getClassLoader()
- Class<?>[](接口数组):真实对象.getClass().getInterfaces()
- InvocationHandler(处理器): new InvocationHandler()
- 例:
Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
2.invoke方法详解
1).参数
- proxy:代理对象 一般不用
- method:代理对象调用的方法,被封装为的对象
- args:代理对象调用方法时,传递的实际参数数组1.增强参数列表
2.增强返回值
3.增强方法体执行逻辑1.创建一个Lenovo类
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
System.out.println("客户花了"+money+"元买了一台联想电脑");
return "联想电脑";
}
@Override
public void show() {
System.out.println("展示电脑");
}
}
2.参数增强
public static void main(String[] args) {
//1.创建真实对象
Lenovo lenovo = new Lenovo();
//2.动态代理增强lenovo对象
SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
//代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1判断是否是sale方法
if (method.getName().equals("sale")) {
//2.增强参数:(代理商要赚钱,将电脑加价)如果是sale方法,增加售价
double money = (double) args[0];
money = money * 1.25;
//3.增强方法体及返回值:(代理商为了欺骗客户,让客户不要产生心理落差)
System.out.println("专车接你....");
String obj = (String) method.invoke(lenovo, money);
System.out.println("免费送货....");
//4.使用真实对象调用该方法,并增强返回值
return obj + "_鼠标垫";
} else {
//4.如果是show方法直接调用真实对象的show方法
Object obj = method.invoke(lenovo, args);
return obj;
}
});
//4.调用方法
String computer = proxy_lenovo.sale(8000);
System.out.println(computer);
//最后输出结果为:
/*
专车接你....
客户花了10000.0元买了一台联想电脑
免费送货....
联想电脑_鼠标垫
*/装饰模式 1.原始类
public class Man implements Person{
@Override
public void eat(){
System.out.println("吃饭");
}
}
2.装饰者模式增强
puliuc class ManWrapper implements Person{
private Person man;
public ManWrapper(Person p){
man = p;
}
public void eat(){
System.out.println("吃饭前喝点水");
man.eat();
System.out.println("吃饭后溜溜弯");
}
}
3.使用装饰的类
public void test1(){
Man man = new Man();
ManWrapper man2 = new ManWrapper(man);
man2.eat();
}继承(不是设计模式) 典型案例登陆校验 1. 访问day17_case案例的资源。验证其是否登录
2. 如果登录了,则直接放行。
3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
//0.强制转换
HttpServletRequest request = (HttpServletRequest)req;
//1.获取资源请求路径
String uri = request.getRequestURI();
//2.判断是否包含登陆相关资源路径
//要注意,还需要排除一些css,js,图片,验证码的资源
if(uri.contains("/login.jsp")||uri.contains("/loginServlet")
||uri.contains("/css/")||uri.contains("/js/")
||uri.contains("/fonts/")||uri.contains("/checkCodeServlet")){
//包含,用户想登陆,放行
chain.doFilter(req,resp);
}else{
//不包含,需要验证用户是否登陆
User user = (User)request.getSession().getAttribute("admin");
//3.判断session中是否存在admin属性
if (user != null) {
//如果存在,则证明用户已经登陆.放行
chain.doFilter(req,resp);
}else{
//如果不存在,则需要用户登陆,转发至login.jsp
request.setAttribute("msg","您尚为登陆,请登陆");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
}
}
}敏感字过滤 1. 对day17_case案例录入的数据进行敏感词汇过滤
2. 敏感词汇参考《敏感词汇.txt》 笨蛋/坏蛋
3. 如果是敏感词汇,替换为 ***@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {
private List<String> list = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//1.获取文件的真实路径
ServletContext context = filterConfig.getServletContext();
String realPath = context.getRealPath("/WEB-INF/classes/敏感词汇.txt");
//2.读取realPath中的敏感词汇
try (FileInputStream fis = new FileInputStream(realPath);
BufferedReader br = new BufferedReader(new InputStreamReader(fis, "utf-8"));) {
//3.使用br读取敏感词汇
String line;
while ((line = br.readLine()) != null) {
list.add(line);
}
System.out.println(list);
//4.不用释放资源了,fis和br的作用域仅在这个try中
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//0.强制转型
HttpServletRequest request = (HttpServletRequest) req;
//1.创建proxy_req对象
HttpServletRequest proxy_req = (HttpServletRequest) Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
//2.1 判断方法是否为getParameter对象
if (methodName.equals("getParameter")) {
String value = (String) method.invoke(request, args);
if (value != null) {
for (String str : list) {
value = value.replaceAll(str, "***");
}
}
return value;
}
//2.2判断方法是否为getParameterValues
if (methodName.equals("getParameterValues")) {
String[] values = (String[]) method.invoke(request, args);
List<String> sb = new ArrayList<>();
if (values != null) {
for (String value : values) {
for (String str : list) {
value = value.replaceAll(str, "***");
}
sb.add(value);
}
}
String[] sBuffer = new String[values.length];
String[] sb_string = sb.toArray(sBuffer);
return sb_string;
}
//2.3判断方法是否为getParameterMap
if (methodName.equals("getParameterMap")) {
Map<String, String[]> map = (Map<String, String[]>) method.invoke(request, args);
Set<String> keys = map.keySet();
Map<String, Object> newMap = new HashMap<>();
for (String key : keys) {
String[] values = map.get(key);
List<String> sb = new ArrayList<>();
for (String value : values) {
for (String str : list) {
value = value.replaceAll(str, "***");
}
sb.add(value);
}
String[] sBuffer = new String[values.length];
String[] sb_string = sb.toArray(sBuffer);
newMap.put(key, sb_string);
}
return newMap;
}
return method.invoke(request, args);
}
});
//3.放行
chain.doFilter(proxy_req, resp);
}
@Override
public void destroy() {
}
}
注:字符流转化
问在FileReader读取文件的过程中,FileReader继承了InputStreamReader,但并没有实现父类中带字符集参数的构造函数,所以FileReader只能按系统默认的字符集来解码,然后在UTF-8 -> GBK -> UTF-8的过程中编码出现损失,造成结果不能还原最初的字符。
用InputStreamReader代替FileReader,InputStreamReader isr=new InputStreamReader(new FileInputStream(fileName),"UTF-8");这样读取文件就会直接用UTF-8解码,不用再做编码转换。
Listener概念:web三大组件之一事件监听机制 事件:一件事情 事件源:事件发生的地方 监听器:一个对象 注册监听:将事件、事件源、监听器绑定在一起,当事件源上发生某个事件后,执行监听代码 ServletContext监听器: ServletContxtListener(现在只学习这一个):监听servletContext对象的创建和销毁
方法1:void contextDestroyed(ServletContextEvent sce) ServletContext对象销毁之前会调用该方法
方法2:void contextInitialized(ServletContextEvent sce) ServletContext对象创建之后会调用该方法1.注解配置
@WebListener
2.web.xml配置
<listener>
<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
</listener>1.void contextInitialized(ServletContextEvent sce):一般用于加载配置文件
设置初始化文件[可以通过servletContext.getInitParameter("参数名")来获取参数值]
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-name>
</context-param>
|
|