手把手写Spring框架

网友投稿 678 2022-12-16

手把手写Spring框架

手把手写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 handlerMappings = new ArrayList();

private Map handlerAdapters = new HashMap();

private List viewResolvers = new ArrayList();

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 paramIndexMapping = new HashMap();

//提取加了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 paramsMap = req.getParameterMap();

//声明实参列表

Object [] parameValues = new Object[paramTypes.length];

for (Map.Entry param : paramsMap.entrySet()) {

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小时内删除侵权内容。

上一篇:vue3实现一个todo
下一篇:简单快速对@RequestParam声明的参数作校验操作
相关文章

 发表评论

暂时没有评论,来抢沙发吧~