文章目录

  • **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框架都可以帮我们找到对应的处理类和处理方法

思路

  1. 遍历所有映射配置的关键字
  2. 把包含*的关键字编译成正则表达式regexKey
  3. 通过regexKey匹配请求地址的方法名
  4. 假如匹配成功,则可以获取到对应的mapping
  5. 需要判断mapping中的方法是否存在占位符,如果存在,则需要把占位符中的索引提取
  6. 通过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实现相关推荐

  1. 大白话聊框架设计(入门篇) | 第四章:简单实现IOC容器

    文章目录 **1.简单实现IOC容器** **2.简单介绍IOC容器** **3.创建Inject注解** **4.创建IocContrainer** **5.初始化IOC容器** **6.改造原有N ...

  2. 大白话聊框架设计(入门篇) | 第二章:规则匹配Mapping实现

    文章目录 **1.规则匹配Mapping实现** **2.重构ActionMapper** **2.1 改造前** **2.2 改造后** **3.创建一个Mapping** **4.创建一个WebC ...

  3. 大白话聊框架设计(入门篇) | 第一章:Filter实现框架拦截

    文章目录 前言 1Filter实现框架拦截 1.1配置自定义Filter 1.2创建一个Filter 1.3创建一个ActionMapping 1.4创建一个ActionMapper 1.5创建一个W ...

  4. OpenGL学习——入门篇 第三章 四个变换及模拟地球公转

    一.四个变换 1.1 视图变换:不同位置观察它: 涉及函数: glMatrixMode(GL_MODELVIEW);//设置当前操作的矩阵为"模型视图矩阵" glLoadIdent ...

  5. 视频教程-Unity客户端框架设计PureMVC篇视频课程(上)-Unity3D

    Unity客户端框架设计PureMVC篇视频课程(上) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过 ...

  6. 视频教程-Unity客户端框架设计PureMVC篇视频课程(下)-Unity3D

    Unity客户端框架设计PureMVC篇视频课程(下) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过 ...

  7. R语言学习笔记——入门篇:第一章-R语言介绍

    R语言 R语言学习笔记--入门篇:第一章-R语言介绍 文章目录 R语言 一.R语言简介 1.1.R语言的应用方向 1.2.R语言的特点 二.R软件的安装 2.1.Windows/Mac 2.2.Lin ...

  8. 第二篇第三章建筑分类与耐火等级

    2019/1/4 [录播]2018一消精华班-实务-一级消防工程师-环球网校 http://v.edu24ol.com/?type=lesson&id=178932&gid=16157 ...

  9. 入门篇 第1章 初始Python

    入门篇 第1章 初始Python 入门篇 第1章  初始Python 1.1  Pyhton 概述 1.1.1 了解 Python Python,本义是指"蟒蛇".1989年,荷兰 ...

最新文章

  1. 高红冰:“五新”创新乡村商业实践
  2. MAX9814高性能麦克风
  3. Kafka Sender线程如何发送数据
  4. mysql子查询设置_什么是mysql子查询?如何利用子查询进行过滤?
  5. Java 对 lang3中Complex类的封装,使之支持BigDecimal
  6. bat获取当前文件夹路径
  7. Nginx之开门见山
  8. python字典占内存_Python:减少字典的内存使用
  9. 锋利的jQuery学习笔记(4)-DOM操作
  10. 如何下载秦皇岛市卫星地图高清版大图
  11. 构建OctoberCMS插件:Google Analytics(分析)
  12. Android开发 RFC 2136 DNS动态更新协议
  13. 于的繁体字有几种写法_“龙”的繁体字有几种写法?
  14. PS_一寸照片换背景底色
  15. feign.RetryableException: connect timed out executing xxxxxx
  16. 一组Android机器人素材图片
  17. css样式的格式是什么,css的语法格式是什么
  18. 程序员如何写好简历 一份优秀的程序员简历是什么样的?
  19. su vs sudo的区别
  20. 关于光纤收发器的一些基本常识介绍

热门文章

  1. 【优秀的系统优化清理维护工具】MacBooster 7 for Mac 7.2.4
  2. 机器学习——使用ID3算法从原理到实际举例理解决策树
  3. 关于动态内表的逆向考勤程序
  4. SpringBoot自定义注解和aop
  5. 自定义SpringBoot启动banner -- 佛祖保佑 永无BUG
  6. Netty 模拟百万连接
  7. 鸿蒙手机壁纸有条纹,百变图标(鸿蒙)
  8. 开源界也要封闭,OpenSource能否继续无国界
  9. 毕莹python_使用 qemu-kvm 安装和运行 Vagrant | Linux 中国
  10. Python使用property函数定义属性访问方法如果不定义fget会怎么样?