大白话聊框架设计(入门篇) | 第三章:通配符匹配Mapping实现
文章目录
- **1.通配符匹配Mapping实现**
- **2.重构ActionMapper**
- **3.修改WebConfig配置**
- **4.新增Mapping构造方法**
- **5.新增PersonAction测试方法**
- **6.最终工程目录结构**
- **7.测试通配符匹配Mapping**
- **7.1 启动tomcat**
- **7.2 在浏览器输入URL**
- **7.3 输出结果**
1.通配符匹配Mapping实现
【思考】
上一章我们学习到如何通过用户请求去匹配Mapping,让框架可以找到对应的处理方法执行用户请求,但是这种方式配置需要满足每个请求的映射,需要重复配置映射文件,我们是否可以通过通配符方式去实现呢?应该如何实现?
2.重构ActionMapper
由上一章,我们学习到了框架如何去匹配用户请求到具体的处理方法,并且引入了配置这个概念,就是通过WebConfig这个类帮我们加载映射配置,从而可以使框架知道用户请求所对应的mapping。例如用户在浏览器输入http://localhost:8080/eshare/hello, 框架帮我们自动调用了PersonAction下的hello方法,我们是通过
mapping.setClassName("com.eshare.action.PersonAction");
mapping.setMethodName("hello");
mapping.setResult("SUCCESS.jsp");
mappings.put("hello",mapping);
预先配置好映射关系,框架才知道hello原来对应的就是PersonAction下的hello方法,但是这有一个弊端,就是假如我换了另外一个方法,我不得不又配置多一个映射关系,如我下次请求是http://localhost:8080/eshare/hi, 以我们目前的做法,我们需要做如下配置:
mapping.setClassName("com.eshare.action.PersonAction");mapping.setMethodName("hi");mapping.setResult("SUCCESS.jsp");mappings.put("hi",mapping);
这样会导致有很多重复的配置,能不能有一种方法可以让一个配置适合多种不同请求呢?这时候就需要用到通配符和占位符了,例如我们在浏览器输入http://localhost:8080/eshare/sayHelloPersonAction,然后通过如下配置:
mapping.setClassName("com.eshare.action.PersonAction");
mapping.setMethodName("{1}");
mapping.setResult("SUCCESS.jsp");
mappings.put("*PersonAction",mapping);
框架能自动识别就是我们任意的请求方法,并把这方法名,自动填充到占位符的位置,PersonAction就是处理请求的类,也就是说这一个配置就可以满足针对PersonAction不同请求的操作,不管是hiPersonAction,或者helloPersonAction框架都可以帮我们找到对应的处理类和处理方法
思路
- 遍历所有映射配置的关键字
- 把包含*的关键字编译成正则表达式regexKey
- 通过regexKey匹配请求地址的方法名
- 假如匹配成功,则可以获取到对应的mapping
- 需要判断mapping中的方法是否存在占位符,如果存在,则需要把占位符中的索引提取
- 通过Matcher中的group方法将占位符填充成我们的目标方法
public class ActionMapper {public ActionMapping findMapping(ServletRequest request) {ActionMapping actionMapping = new ActionMapping();//把请求实体类型转换成HttpServletRequestHttpServletRequest req = (HttpServletRequest) request;//从请求实体中获取UriString uri = req.getRequestURI();//根据Uri地址截取用户请求的方法名String methodName = uri.substring(req.getContextPath().length() + 1);//从配置文件获取所有规则匹配映射WebConfig webConfig = new WebConfig();Map<String, Mapping> mappings = webConfig.getMappings();//根据请求方法名找到匹配的映射类Mapping mapping = mappings.get(methodName);//根据通配符查找mappingif (mapping == null) {//遍历所有mappings里的所有keyIterator<String> iter = mappings.keySet().iterator();while (iter.hasNext()) {String matchKey = iter.next();//匹配当前请求方法,如匹配则返回对应的mappingactionMapping = matchMapping(methodName, matchKey, mappings);if (actionMapping != null) {return actionMapping;}}} else {return convertActionMapping(methodName, mapping);}return actionMapping;}/*** 转换ActionMapping** @param methodName* @param mapping*/private ActionMapping convertActionMapping(String methodName, Mapping mapping) {//把mapping转换成对应的actionMapping返回ActionMapping actionMapping = new ActionMapping();actionMapping.setClassName(mapping.getClassName());actionMapping.setMethodName(methodName);actionMapping.setResult(mapping.getResult());return actionMapping;}/*** 匹配映射* <pre>* methodName:helloPersonAction* matchKey: *PersonAction* mapping:new Mapping("com.eshare.action.PersonAction","{1}","SUCCESS.jsp")* </pre>** @param methodName 方法名* @param matchKey 匹配关键字* @param mappings 映射配置* @return*/private ActionMapping matchMapping(String methodName, String matchKey, Map<String, Mapping> mappings) {String regexKey = matchKey;//查看当前关键字是否包含通配符*if (matchKey.contains("*")) {//对通配符替换成正则表达式regexKey = matchKey.replaceAll("\\*", "(\\.\\*)");}//把关键字编译成正则表达式实例Pattern pattern = Pattern.compile(regexKey);Matcher matcher = pattern.matcher(methodName);Mapping mapping;//通过正则表达式与方法名相匹配if (matcher.find()) {//匹配上则通过关键字去查找对应的mappingmapping = mappings.get(matchKey);//框架使用者配置的方法参数名称String configMethod = mapping.getMethodName();//请求实际的处理方法String method;//配置的方法是否有括号,如果存在,则是一个占位符if (configMethod.contains("{")) {//把所有括号去掉configMethod = configMethod.replaceAll("\\{", "").replaceAll("\\}", "");//把数字转换成索引int index = Integer.valueOf(configMethod);//通过matcher的group方法将请求方法与占位符匹配替换method = matcher.group(index);} else {//假如配置方法参数不存在占位符,则直接是最后的执行方法名method = configMethod;}//把解析出来的处理方法名存储到mapping中,替换原来的占位符return convertActionMapping(method, mapping);}return null;}}
3.修改WebConfig配置
本章我们需要将WebConfig中的映射配置改成通配符方式,模拟配置文件中,用通配符做映射
/*** 加载映射配置*/public void loadMappingConfigs(){mappings = new HashMap<String, Mapping>();Mapping mapping = new Mapping();/* //模拟框架扫描到所有框架使用者配置的映射配置mapping.setClassName("com.eshare.action.PersonAction");mapping.setMethodName("hello");mapping.setResult("SUCCESS.jsp");//模拟配置文件把规则匹配与映射类存放mappings.put("hello",mapping);*///通过通配符方式绑定mappingmappings.put("*PersonAction",new Mapping("com.eshare.action.PersonAction","{1}","SUCCESS.jsp"));}
4.新增Mapping构造方法
在Mapping类的原基础上,新增一个构造方法,主要适用于WebConfig使用。
public Mapping(String className, String methodName, String result) {this.className = className;this.methodName = methodName;this.result = result;}
5.新增PersonAction测试方法
新增一个sayHello方法,用于区分前面章节的例子
public String sayHello(){System.out.println("sayHello ch3");boolean flag = false;if(flag){return "SUCCESS";}else {return "FAILE";}}
6.最终工程目录结构
7.测试通配符匹配Mapping
7.1 启动tomcat
7.2 在浏览器输入URL
我的上下文路径是eshare
http://localhost:8080/eshare/sayHelloPersonAction
7.3 输出结果
大白话聊框架设计(入门篇) | 第三章:通配符匹配Mapping实现相关推荐
- 大白话聊框架设计(入门篇) | 第四章:简单实现IOC容器
文章目录 **1.简单实现IOC容器** **2.简单介绍IOC容器** **3.创建Inject注解** **4.创建IocContrainer** **5.初始化IOC容器** **6.改造原有N ...
- 大白话聊框架设计(入门篇) | 第二章:规则匹配Mapping实现
文章目录 **1.规则匹配Mapping实现** **2.重构ActionMapper** **2.1 改造前** **2.2 改造后** **3.创建一个Mapping** **4.创建一个WebC ...
- 大白话聊框架设计(入门篇) | 第一章:Filter实现框架拦截
文章目录 前言 1Filter实现框架拦截 1.1配置自定义Filter 1.2创建一个Filter 1.3创建一个ActionMapping 1.4创建一个ActionMapper 1.5创建一个W ...
- OpenGL学习——入门篇 第三章 四个变换及模拟地球公转
一.四个变换 1.1 视图变换:不同位置观察它: 涉及函数: glMatrixMode(GL_MODELVIEW);//设置当前操作的矩阵为"模型视图矩阵" glLoadIdent ...
- 视频教程-Unity客户端框架设计PureMVC篇视频课程(上)-Unity3D
Unity客户端框架设计PureMVC篇视频课程(上) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过 ...
- 视频教程-Unity客户端框架设计PureMVC篇视频课程(下)-Unity3D
Unity客户端框架设计PureMVC篇视频课程(下) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过 ...
- R语言学习笔记——入门篇:第一章-R语言介绍
R语言 R语言学习笔记--入门篇:第一章-R语言介绍 文章目录 R语言 一.R语言简介 1.1.R语言的应用方向 1.2.R语言的特点 二.R软件的安装 2.1.Windows/Mac 2.2.Lin ...
- 第二篇第三章建筑分类与耐火等级
2019/1/4 [录播]2018一消精华班-实务-一级消防工程师-环球网校 http://v.edu24ol.com/?type=lesson&id=178932&gid=16157 ...
- 入门篇 第1章 初始Python
入门篇 第1章 初始Python 入门篇 第1章 初始Python 1.1 Pyhton 概述 1.1.1 了解 Python Python,本义是指"蟒蛇".1989年,荷兰 ...
最新文章
- 高红冰:“五新”创新乡村商业实践
- MAX9814高性能麦克风
- Kafka Sender线程如何发送数据
- mysql子查询设置_什么是mysql子查询?如何利用子查询进行过滤?
- Java 对 lang3中Complex类的封装,使之支持BigDecimal
- bat获取当前文件夹路径
- Nginx之开门见山
- python字典占内存_Python:减少字典的内存使用
- 锋利的jQuery学习笔记(4)-DOM操作
- 如何下载秦皇岛市卫星地图高清版大图
- 构建OctoberCMS插件:Google Analytics(分析)
- Android开发 RFC 2136 DNS动态更新协议
- 于的繁体字有几种写法_“龙”的繁体字有几种写法?
- PS_一寸照片换背景底色
- feign.RetryableException: connect timed out executing xxxxxx
- 一组Android机器人素材图片
- css样式的格式是什么,css的语法格式是什么
- 程序员如何写好简历 一份优秀的程序员简历是什么样的?
- su vs sudo的区别
- 关于光纤收发器的一些基本常识介绍
热门文章
- 【优秀的系统优化清理维护工具】MacBooster 7 for Mac 7.2.4
- 机器学习——使用ID3算法从原理到实际举例理解决策树
- 关于动态内表的逆向考勤程序
- SpringBoot自定义注解和aop
- 自定义SpringBoot启动banner -- 佛祖保佑 永无BUG
- Netty 模拟百万连接
- 鸿蒙手机壁纸有条纹,百变图标(鸿蒙)
- 开源界也要封闭,OpenSource能否继续无国界
- 毕莹python_使用 qemu-kvm 安装和运行 Vagrant | Linux 中国
- Python使用property函数定义属性访问方法如果不定义fget会怎么样?