当前位置:网站首页>装饰器模式的应用,包装ServletRequest,增加addParameter方法
装饰器模式的应用,包装ServletRequest,增加addParameter方法
2022-06-29 08:55:00 【milugloomy】
什么是装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
关键词:现有的对象,添加新功能。
通过子类的方式是对父类添加新的功能,针对的是类。而装饰器模式针对的是一个现有的对象,而不是类。
解释
看下面的例子:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequestWrapper servletRequest = (HttpServletRequestWrapper) req;
AuthServletRequest request = new AuthServletRequest(servletRequest);
//...
chain.doFilter(request, req);
}这里的servletRequest就是一个现有的对象,在这里我们要动态的扩展servletRequest的方法,通过子类继承的方式不太好实现,但通过装饰器模式就很方便的可以实现。
AuthServletRequest就是装饰类,包装了原有的servletRequest,在保证servletRequest完整的情况下,实现了额外的功能。
增加方法
项目中使用了网关,网关解析出jwt后,将userId和role通过header传到业务项目,结构图如下:

业务项目拿到userId和role后,希望能塞入HttpRequest的parameter,这样在spring项目的Controller中就能直接定义在方法上了,简化业务项目的开发。类似这样:
RequestMapping("/sysUser")
public MyResEntity sysUser(Integer userId){
SysUser sysUser = sysUserService.sysUser(userId);
return new MyResEntity(sysUser);
}但是HttpServletRequest没有增加参数到parameter这个方法,没法实现上述需求。
这里就轮到装饰器模式派上用场了。新增AuthServletRequest类,如下:
public class AuthServletRequest extends HttpServletRequestWrapper {
// 存储request数据的Map
private Map<String, String[]> params = new HashMap<String, String[]>();
public AuthServletRequest(HttpServletRequestWrapper request) {
super(request);
//将现有parameter传递给params
this.params.putAll(request.getParameterMap());
}
//重写getParameter,代表参数从当前类中的map获取
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
//重写getParameterValues,代表参数从当前类中的map获取
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
// 核心方法,新增添加parameter的方法
public void addParameter(String name, Object value) {
if (value != null) {
System.out.println(value);
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{(String) value});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
}
}然后新增一个过滤器AuthFilter,代码如下:
public class AuthFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequestWrapper servletRequest = (HttpServletRequestWrapper) req;
AuthServletRequest request = new AuthServletRequest(servletRequest);
HttpServletResponse response = (HttpServletResponse) res;
// header里的值是gateway解析jwt得出的值
String userId = request.getHeader("userId");
if (userId != null && request.getParameter("userId") == null) {
request.addParameter("userId", userId);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
结论
我们通过装饰器模式,在项目运行时动态的给ServletRequest增加了addParameter方法,扩展了原对象。
装饰器模式是继承的一种替代模式,其优点是可以动态扩展一个实现类的功能。装饰器模式在jdk和各大框架中都有广泛的应用,例如:
在Java中,InputStream,FileInputStream,BufferedInputStream等IO流的操作就运用了装饰器模式。
在spring使用redis实现session共享的功能里,spring也使用装饰器模式包装了HttpServletRequest,装饰类为SessionRepositoryRequestWrapper,其中重写了getSession方法,从redis中创建和获取session对象。
边栏推荐
- Pytorch summary learning series - operation
- Go deep into RC, RS, daemonset and statefulset (VII)
- Mh/t 6040 smoke density test of aviation materials
- A comparison of methods for fully automatic segmentation of tumors and involved nodes in PET/CT of h
- 转载 :判断对象是否具有属性的5种方法
- Western Polytechnic University, one of the "seven national defense schools", was attacked by overseas networks
- Idea auto completion
- The 23 most useful elasticsearch search techniques you must know
- 股票炒股账号开户安全吗?是靠谱的吗?
- Research progress of target detection in the era of deep convolutional neural network
猜你喜欢

In the era of data processing, data quality construction is the way for enterprises to survive

A 2.5D Cancer Segmentation for MRI Images Based on U-Net

Automatic 3D Detection and Segmentation of Head and Neck Cancer from MRI Data.

Written test question "arrange version numbers from large to small"

数据可视化:数据可视化四象限,教你正确应用图标

基於PyQt5和Qt Designer的簡易加法計算器的制作

Deep Learning-based Automated Delineation of Head and Neck Malignant Lesions from PET Images

SPI drive of lsm6dsl

Simplicity studio does not recognize the new JLINK V9 solution

User level threads and kernel level threads
随机推荐
Summary of 3DMAX jamming, white screen and rendering crash
Have you done the network security "physical examination" this year?
Segmentation of Head and Neck Tumours Using Modified U-net
用户级线程和内核级线程
A comparison of methods for fully automatic segmentation of tumors and involved nodes in PET/CT of h
InvalidConnectionAttributeException异常处理
【华为认证】HCIA-DATACOM史上最全精选题库(附答案解析)
UE4 在4.20-23版本安裝Datasmith插件
你知道BFD是什么吗?一文详解BFD协议原理及使用场景
股票炒股账号开户安全吗?是靠谱的吗?
Gross Tumor Volume Segmentation for Head and Neck Cancer Radiotherapy using Deep Dense Multi-modalit
Wechat applet custom multi selector
Making of simple addition calculator based on pyqt5 and QT Designer
第十二章 信号(二)- 生产者消费者示例
Western Polytechnic University, one of the "seven national defense schools", was attacked by overseas networks
Segmentation of Head and Neck Tumours Using Modified U-net
UE4 VS的Visual Assist插件设置
Wechat applet latest canvas2d handwritten signature
UE4 材质UV纹理不随模型缩放拉伸
UE4 compile a single file (VS and editor start respectively)