DispatcherServlet:分发、调度
根据上一节,已经实现了将controller的方法添加到容器中,而DispatcherServlet的作用就是接收来自客户端的请求,然后通过URI的组合,来找到对应的@RequestMapping注解的方法,调用对应的方法,最后返回响应
第一步:获取URI,根据URI来匹配对应的BeanDefinition
String requestURI = req.getRequestURI();
Map<String, BeanDefinition<?>> maps = BeanContainer.getMaps();
//通过匹配URI来找到对应的BeanDefinition
BeanDefinition<?> beanDefinition = maps.get(requestURI);
if (beanDefinition == null) {
throw new FrameWorkException(ResponseCode.REQUEST_MAPPING_PATH_EXCEPTION.getCode(), ResponseCode.REQUEST_MAPPING_PATH_EXCEPTION.getMessage());
}
第二步:获取容器中的BeanDefinition的MethodDefinition和ParameterDefinition
//获取对应的controller类对象
Object t = beanDefinition.getT();
MethodDefinition methodDefinition = beanDefinition.getMethodDefinition();
//获取方法对象
Method method = methodDefinition.getMethod();
method.setAccessible(true);
//获取参数列表
List<ParameterDefinition> parameterDefinitions = methodDefinition.getParameters();
第三步:调用对应的方法
Object[] args;
Model model = new Model();
try {
args = handlerParameterArgs(parameterDefinitions, req, resp, model);
//调用Controller层里某个方法
Object returnVal = method.invoke(t, args);
if (returnVal != null) {
//处理返回值
handlerReturnVal(methodDefinition, returnVal, req, resp, model);
}
} catch (Exception e) {
System.out.println(Arrays.toString(e.getStackTrace()));
;
}
handlerParameterArgs:将调用的方法的参数列表与请求数据适配
/**
* 集中处理参数的函数,通过判断参数的类型,对不同类型的参数进行处理,包括
* 1. 常见参数类型:八大基本数据类型及其包装类 + String
* 2. 数组类型
* 3. HttpServletRequest 类型
* 4. httpServletResponse 类型
* 5. List<?> 类型
* 6. 自定义类型
*
* @param parameterDefinitions 参数描述对象列表(从controller的方法下抽取出来的)
* @param req 请求对象
* @param resp 响应对象
* @param model 数据体(应该是,里面是Map,key为数据名,value为数据体,最后通过装载到request对象转发出去)
* @return 参数列表 Object[] args
*/
public Object[] handlerParameterArgs(List<ParameterDefinition> parameterDefinitions, HttpServletRequest req, HttpServletResponse resp, Model model) throws ClassNotFoundException {
if (parameterDefinitions == null) {
return null;
}
//实际参数的列表
Object[] args = new Object[parameterDefinitions.size()];
//将请求中的参数添加到args中
for (ParameterDefinition parameterDefinition : parameterDefinitions) {
String name = parameterDefinition.getParameterName();//参数名
Class<?> type = parameterDefinition.getType();//参数类型
int index = parameterDefinition.getIndex();//参数下标
if (