装饰 HttpServletRequest 对象
需求:在 HttpServletRequest 对象到达 Servlet 之前把用户输入的多余空格都去掉
情景:因为 HttpServletRequest 对象里的请求参数都实际包含在 java.util.Map 对象里,而Map是不允许修改的,所以包含在 HttpServletRequest 对象里的请求参数不能被修改
解决方案:采取 Decorator(装饰器)模式
为何使用装饰模式增强HttpServletRequest(为何使用HttpServletRequestWrapper )? 先看下面实现敏感内容处理的过滤器的实现:
package org.rabbitx.web.javaweb.filter.example; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.rabbitx.web.javaweb.filter.HttpFilter; import org.rabbitx.web.javaweb.filter.MyHttpServletRequest; public class ContentFilter extends HttpFilter{ public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { //1. 获取请求 content 参数的值 String content = request.getParameter("content"); //2. 把其中 fuck, shit 等字符串替换换为 **** if(content.contains(" fuck ")){ //ServletRequest, HttpServletRequest 中并没有提供诸如 setParameter(paramName, paramValue) //类似于这样的方法. //目标: 改变 HttpServletRequest 的 getParameter(String) 方法的行为: 若该方法的返回值中 //包含 " fuck ", 则替换为 " **** " } //3. 转到目标页面 filterChain.doFilter(req, response); } }
实现中发现一个问题,ServletRequest, HttpServletRequest 中并没有提供诸如 setParameter(paramName, paramValue)类似于这样的方法.所以我们只能尝试重写getParameter(String)方法:
1. 若对于一个类的方法不满意, 需要进行重写, 最常见的方式是, 继承父类, 重写方法. 若实现则需要继承 org.apache.catalina.connector.RequestFacade, 而这仅是 Tomcat服务器的实现, 若更换服务器, 该方案将无法使用. 与具体容器耦合,没有移植性.
2. 直接写一个 HttpServletRequest 接口的实现类: 很麻烦,而且也需要和具体的容器相耦合.
发现上面两种方法都不理想,来看下第三种方法:
装饰目前的 HttpServletRequest 对象: 装饰其 getParameter 方法, 而其他方法还和其实现相同.创建一个类, 该类实现 HttpServletRequest 接口, 把当前 doFilter 中的 request 传入到该类中, 作为其成员变量, 使用该成员变量去实现接口的全部方法. 对无需要增强或改变的方法,可以在装饰类中重写。
具体实现
package org.rabbitx.web.javaweb.filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class MyHttpServletRequest extends HttpServletRequestWrapper{ public MyHttpServletRequest(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String val = super.getParameter(name); if(val != null && val.contains(" fuck ")){ val = val.replace("fuck", "****"); } return val; } }
package org.rabbitx.web.javaweb.filter.example; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.rabbitx.web.javaweb.filter.HttpFilter; import org.rabbitx.web.javaweb.filter.MyHttpServletRequest; public class ContentFilter extends HttpFilter{ public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { //1. 获取请求 content 参数的值 String content = request.getParameter("content"); //此处为实现 HttpServletRequest req = new MyHttpServletRequest(request); //3. 转到目标页面 filterChain.doFilter(req, response); } }
HttpServletWrapper 和 HttpServletResponseWrapper
1). Servlet API 中提供了一个 HttpServletRequestWrapper 类来包装原始的 request 对象,
HttpServletRequestWrapper 类实现了 HttpServletRequest 接口中的所有方法,
这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法
//包装类实现 ServletRequest 接口.
public class ServletRequestWrapper implements ServletRequest {
//被包装的那个 ServletRequest 对象
private ServletRequest request;
//构造器传入 ServletRequest 实现类对象
public ServletRequestWrapper(ServletRequest request) {
if (request == null) {
throw new IllegalArgumentException("Request cannot be null");
}
this.request = request;
}
//具体实现 ServletRequest 的方法: 调用被包装的那个成员变量的方法实现。
public Object getAttribute(String name) {
return this.request.getAttribute(name);
}
public Enumeration getAttributeNames() {
return this.request.getAttributeNames();
}
//...
}
相类似 Servlet API 也提供了一个 HttpServletResponseWrapper 类来包装原始的 response 对象
2). 作用: 用于对 HttpServletRequest 或 HttpServletResponse 的某一个方法进行修改或增强.
public class MyHttpServletRequest extends HttpServletRequestWrapper{
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String val = super.getParameter(name);
if(val != null && val.contains(" fuck ")){
val = val.replace("fuck", "****");
}
return val;
}
}
3). 使用: 在 Filter 中, 利用 MyHttpServletRequest 替换传入的 HttpServletRequest
HttpServletRequest req = new MyHttpServletRequest(request);
filterChain.doFilter(req, response);
此时到达目标 Servlet 或 JSP 的 HttpServletRequest 实际上是 MyHttpServletRequest
Decorator 模式
因为继承的关系,当需要改变某个对象的行为时,只须扩展这个对象所属的类并重写其有关的方法就可以达到目的。但是,当想要改变其行为的对象是由应用程序里的另一个子系统(例如:一个对象工厂或是一个Servlet 容器)负责构造,继承机制将无能为力
Decorator 模式----情景
已知:Messager 类的定义(可以从它派生处一个之类);Messager 对象总是来自一个对象工厂(MessagerFactory),该工厂可以对它创建的每一个 Messager 对象进行初始化----通过调用 getMessage() 方法而获得的 message 属性也不例外(即不能对 Messager 对象进行初始化)
假设:需要使用 Messager 类的 getMessage() 方法。有一个Util的使用工具类,该类中有如下方法:
public static void broadcast(Message messager){
System.out.println(messager.getMessage());
}
Decorator 模式----需求,方案
需求:让 broadcast 方法打印的字母都是大写字母
方案:从 Messager 类派生一个子类,把子类对象传递给 broadcast 方法。因为只有对象工厂知道如何初始化 Messager 对象,所以该方案无意义
Decorator 模式:
从 Messager 类派生一个子类 MessagerDecorator,把子类对象传递给 broadcast 方法
在 MessagerDecorator 类里实现构造器:接受一个 Messager 对象作为输入参数,而这个 Messager 就是想要装饰的对象:public MessagerDecorator(Messager messager)
重写 getMessage 方法,让重写的方法用大写字母来返回 message 属性
HttpServletRequestWrapper 类
Servlet API 中提供了一个 HttpServletRequestWrapper 类来包装原始的 request 对象, HttpServletRequestWrapper 类实现了 HttpServletRequest 接口中的所有方法,这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法
相类似 Servlet API 也提供了一个 HttpServletResponseWrapper 类来包装原始的 response 对象
相关推荐
JAVAWEB-09:HttpServletRequest对象&会话管理之Cookie
JavaWeb开发技术-HttpServletRequest对象.pptx
JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...
JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...
javaweb传值对象.xlsjavaweb传值对象.xlsjavaweb传值对象.xls
JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...
JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...
李兴华javaweb之JSP基础语法(上)笔记
JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...
javaWEB总结(7):HttpServlet和HttpServletRequest试验代码
javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码...
本学期javaWeb课程实验源码,本次实验是练习jsp内置对象的使用,包括登录注册以及验证共4个jsp页面,另外还有一个cookies的操作页面,具体教程可看本人博客
JavaWeb开发技术-Cookie对象.pptx
JavaWeb开发技术-HttpServletResponse对象.pptx
JavaWeb开发技术-RequestDispatcher对象.pptx
JavaWeb教材配套资源,内含每个章节的Demo项目源码。包含教材最后完整的网上商城案例源码,包含sql及项目源码。 public class TestServlet01 extends HttpServlet { private static final long serialVersionUID = ...
JavaWeb 开发之路经验总结
JavaWeb讲义:JavaWeb应用简介
JavaWeb毕业设计之学生信息管理系统源码(源码+数据库) JavaWeb管理系统源码、javaweb项目完整案例、javaweb学生管理系统、JavaWeb毕业设计、jsp学生信息管理系统