洞察在数字化转型过程中,信创推动企业有效整合资源,实现低成本、高效率的跨平台小程序运营。
722
2022-12-16
手把手写Spring框架
目录初始化阶段运行阶段HandlerAdapter形参列表:编译后就能拿到值实参列表:要运行时才能拿到值最后反射总结:
这部分目标是MVC!
主要完成3个重要组件:
HandlerMapping:保存URL映射关系
HandlerAdapter:动态参数适配器
ViewResolvers:视图转换器,模板引擎
SpringMVC核心组件执行流程:
相对应的,用以下几个类来实现上述的功能:
初始化阶段
在DispatcherServlet这个类的init方法中,将mvc部分替换为initStrategies(context):
并且调用初始化三个组件的方法。
分别完善这几个方法:
private void initViewResolvers(PigApplicationContext context) {
//模板引擎的根路径
String tempateRoot = context.getConfig().getProperty("templateRoot");
String templateRootPath = this.getClass().getClassLoader().getResource(tempateRoot).getFile();
File templateRootDir = new File(templateRootPath);
for (File file : templateRootDir.listFiles()) {
this.viewResolvers.add(new PIGViewResolver(tempateRoot));
}
}
private void initHandlerAdapters(PigApplicationContext context) {
for (PIGHandlerMapping handlerMapping : handlerMappings) {
this.handlerAdapters.put(handlerMapping,new PIGHandlerAdapter());
}
}
private void initHandlerMappings(PigApplicationContext context) {
if(context.getBeanDefinitionCount() == 0){ return; }
String [] beanNames = context.getBeanDefinitionNames();
for (String beanName : beanNames) {
Object instance = context.getBean(beanName);
Class> clazz = instance.getClass();
if(!clazz.isAnnotationPresent(PIGController.class)){ continue; }
String baseUrl = "";
if(clazz.isAnnotationPresent(PIGRequestMapping.class)){
PIGRequestMapping requestMapping = clazz.getAnnotation(PIGRequestMapping.class);
baseUrl = requestMapping.value();
}
//默认只获取public方法
for (Method method : clazz.getMethods()) {
if(!method.isAnnotationPresent(PIGRequestMapping.class)){continue;}
PIGRequestMapping requestMapping = method.getAnnotation(PIGRequestMapping.class);
// //demo//query
String regex = ("/" + baseUrl + "/" + requestMapping.value().replaceAll("\\*",".*")).replaceAll("/+","/");
Pattern pattern = Pattern.compile(regex);
handlerMappings.add(new PIGHandlerMapping(pattern,instance,method));
System.out.println("Mapped " + regex + "," + method);
}
}
}
全局变量:
private List
private Map
private List
HandlerMapping与HandlerAdapter是一一对应的关系。
运行阶段
整体思路:
getHandler就是通过请求拿到URI,并与handlerMappings中存好的模板进行匹配:
private PIGHandlerMapping getHandler(HttpServletRequest req) {
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replaceAll(contextPath,"").replaceAll("/+","/");
for (PIGHandlerMapping handlerMapping : this.handlerMappings) {
Matcher matcher = handlerMapping.getPattern().matcher(url);
if(!matcher.matches()){continue;}
return handlerMapping;
}
return null;
}
HandlerAdapter
HandlerAdapter的handle方法负责反射调用具体方法。需要匹配参数,那么需要先保存好实参和形参列表。
形参列表:编译后就能拿到值
Map
//提取加了PIGRequestParam注解的参数的位置
Annotation[][] pa = handler.getMethod().getParameterAnnotations();
for (int i = 0; i < pa.length; i ++){
for (Annotation a : pa[i]) {
if(a instanceof PIGRequestParam){
String paramName = ((PIGRequestParam) a).value();
if(!"".equals(paramName.trim())){
paramIndexMapping.put(paramName,i);
}
}
}
}
//提取request和response的位置
Class> [] paramTypes = handler.getMethod().getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
Class> type = paramTypes[i];
if(type == HttpServletRequest.class || type == HttpServletResponse.class){
http:// paramIndexMapping.put(type.getName(),i);
}
}
实参列表:要运行时才能拿到值
Map
//声明实参列表
Object [] parameValues = new Object[paramTypes.length];
for (Map.Entry
String value = Arrays.toString(paramsMap.get(param.getKey()))
.replaceAll("\\[|\\]","")
.replaceAll("\\s","");
if(!paramIndexMapping.containsKey(param.getKey())){continue;}
int index = paramIndexMapping.get(param.getKey());
parameValues[index] = caseStringVlaue(value,paramTypes[index]);
}
if(paramIndexMapping.containsKey(HttpServletRequest.class.getName())){
int index = paramIndexMapping.get(HttpServletRequest.class.getName());
parameValues[index] = req;
}
if(paramIndexMapping.containsKey(HttpServletResponse.class.getName())){
int index = paramIndexMapping.get(HttpServletResponse.class.getName());
parameValues[index] = resp;
}
最后反射
总结:
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~