`

JavaWeb之装饰 HttpServletRequest 对象

 
阅读更多

 

装饰 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开发技术-HttpServletRequest对象.pptx

    HttpServletRequest 对象是 JavaWeb 开发中最常用的对象之一,它提供了一系列方法来获取 HTTP 请求的相关信息。在本文中,我们将详细介绍 HttpServletRequest 对象的使用方法和应用场景。 获取请求行信息的方法 在...

    JAVAWEB-09:HttpServletRequest对象&会话管理之Cookie

    在JavaWeb开发中,`HttpServletRequest`对象和会话管理是两个关键的概念,它们构成了Web应用程序交互的基础。这次我们将深入探讨这两个主题,特别是关于Cookie的使用。 `HttpServletRequest`对象是Servlet API的一...

    JavaWeb04-内置对象与include指令.rar

    JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...

    JavaWeb开发技术-HttpServletResponse对象.pptx

    JavaWeb开发技术-HttpServletResponse对象 JavaWeb开发技术中,HttpServletResponse对象是Servlet容器提供的一个对象,用于向客户端发送响应信息。在每次Servlet请求时,Web服务器都会创建一个HttpServletResponse...

    javaWeb课程实验2--jsp内置对象

    JavaWeb课程实验主要聚焦在JSP(JavaServer Pages)技术的应用,特别是JSP的内置对象。JSP是一种基于Java的动态网页技术,它允许开发者在HTML代码中嵌入Java代码,使得网页具备处理服务器端逻辑的能力。这次实验的...

    JavaWeb12-文件上传.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内置对象作业:使用session完成简单购物车功能

    - 在Servlet或JSP脚本中,使用`HttpServletRequest`的`getSession()`方法获取`session`对象,然后进行数据的读写操作。 - 最后,将处理后的数据通过`request.setAttribute()`传递回JSP页面,用EL(Expression ...

    北大青鸟javaweb

    本资源摘要信息将详细阐述北大青鸟javaweb相关知识点,涵盖JSP隐式对象、输入/输出对象、作用域通信对象、Servlet相关对象、错误对象等内容。 JSP隐式对象 JSP隐式对象是Web容器加载的一组类,不需要使用“new”...

    李兴华JavaWeb培训经典笔记

    在JavaWeb中,"四种属性范围 内置对象.pdf"可能会详细讲解四大作用域(page、request、session、application)以及它们对应的内置对象,如PageContext、HttpServletRequest、HttpSession和ServletContext。这些对象...

    javaweb传值对象.xls

    javaweb传值对象.xlsjavaweb传值对象.xlsjavaweb传值对象.xls

    javaWEB总结(7):HttpServlet和HttpServletRequest

    在JavaWeb_07这个压缩包中,很可能包含了实现上述功能的示例代码,你可以通过查看这些代码来加深对`HttpServlet`和`HttpServletRequest`的理解。这些代码可能包括了创建自定义Servlet、覆盖处理方法、获取和处理请求...

    JavaWeb11-图片验证码.rar

    JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...

    JavaWeb05-购物车.rar

    JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...

    JavaWeb讲义:JavaWeb应用简介

    JavaWeb技术是构建互联网应用程序的一种强大工具,它基于Java平台,为开发动态、交互式的Web应用提供了丰富的功能。本讲义将重点介绍JavaWeb的基本概念、核心组件以及常用框架。 一、JavaWeb应用概述 JavaWeb应用是...

    李兴华javaweb之JSP基础语法(上)笔记

    李兴华javaweb之JSP基础语法(上)笔记

    javaWEB 人力资源管理系统源码

    javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码javaWEB 人力资源管理系统源码...

    JavaWeb07-javaWeb模式.rar

    JavaWeb04-内置对象与include指令.rar JavaWeb05-购物车.rar JavaWeb06-Servlet.rar JavaWeb07-javaWeb模式.rar JavaWeb08-DBUtil.rar JavaWeb09-EL与JSTL.rar JavaWeb10-分页应用.rar JavaWeb11-图片验证码.rar ...

    JavaWeb程序设计入门课件Cookie对象共6页.pd

    【JavaWeb程序设计入门课件Cookie对象共6页.pdf.zip】是一个压缩文件,其中包含了关于JavaWeb开发中Cookie对象的基础教程。Cookie是Web应用程序中用于存储客户端信息的一种机制,它是HTTP协议无状态特性的一种补充。...

    JavaWeb开发技术-RequestDispatcher对象.pptx

    RequestDispatcher 对象在 JavaWeb 开发中的应用 RequestDispatcher 对象是 JavaWeb 开发中的一种重要对象,它允许开发者在服务器端将请求从一个资源传递给另一个资源,以实现更灵活的请求处理机制。在本文中,我们...

Global site tag (gtag.js) - Google Analytics