一.手写mvc前基础知识
1.mvc是什么?
MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
2.mvc能帮我们做什么?
1.让我们能非常简单的设计出干净的Web层和薄薄的Web层;
2.进行更简洁的Web层的开发;
3.提供强大的约定大于配置的契约式编程支持;
4.能简单的进行Web层的单元测试;
5.支持灵活的URL到页面控制器的映射;
6.非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API
7.更加简单的异常处理。
等等...
3.spring mvc 架构图
二. 手写mvc实现过程
1.定义配置标记
1.@RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系
2.@RequestParam:请求的方法参数名称
3.@ResponseBody:用于标记自动对返回值进行json处理
2.转发控制器
核心流程:
1.初始化
- 1.初始化容器
- 2.doAop
- 3.doIoc
- 4.初始化请求处理器责任链
2.处理请求
-
1.创建责任链对象实例
-
2.通过责任链模式来依次调用请求处理器对请求进行处理
-
3.对处理结果进行渲染
package org.simplespring.mvc;
import org.simplespring.aop.AspectWeaver;
import org.simplespring.core.BeanContainer;
import org.simplespring.inject.DependencyInjector;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.processor.impl.ControllerRequestProcessor;
import org.simplespring.mvc.processor.impl.JspRequestProcessor;
import org.simplespring.mvc.processor.impl.PreRequestProcessor;
import org.simplespring.mvc.processor.impl.StaticResourceRequestProcessor;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* 请求转发器
*/
@WebServlet("/*")
public class DispatcherServlet extends HttpServlet {
List<RequestProcessor> PROCESSOR = new ArrayList<>();
/**
* 初始化
* 1.初始化容器
* 2.doAop
* 3.doIoc
* 4.初始化请求处理器责任链
*/
@Override
public void init(){
//1.初始化容器
BeanContainer beanContainer = BeanContainer.getInstance();
beanContainer.loadBeans("com.zhangtianci");
new AspectWeaver().doAop();
new DependencyInjector().doIoc();
//2.初始化请求处理器责任链
PROCESSOR.add(new PreRequestProcessor());
PROCESSOR.add(new StaticResourceRequestProcessor(getServletContext()));
PROCESSOR.add(new JspRequestProcessor(getServletContext()));
PROCESSOR.add(new ControllerRequestProcessor());
}
/**
* 1.创建责任链对象实例
* 2.通过责任链模式来依次调用请求处理器对请求进行处理
* 3.对处理结果进行渲染
* @param req
* @param resp
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
//1.创建责任链对象实例
RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
//2.通过责任链模式来依次调用请求处理器对请求进行处理
requestProcessorChain.doRequestProcessorChain();
//3.对处理结果进行渲染
requestProcessorChain.doRender();
}
}
3.请求处理责任链
1.以责任链的模式执行注册的请求处理器
2.委派给特定的Render实例对处理后的结果进行渲染
package org.simplespring.mvc;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.render.DefaultResultRender;
import org.simplespring.mvc.render.InternalErrorResultRender;
import org.simplespring.mvc.render.ResultRender;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
/**
* 请求处理责任链
*
* 1.以责任链的模式执行注册的请求处理器
* 2.委派给特定的Render实例对处理后的结果进行渲染
*/
@Data
@Slf4j
public class RequestProcessorChain {
//请求处理器迭代器
private Iterator<RequestProcessor> requestProcessorIterator;
//请求request
private HttpServletRequest request;
//请求response
private HttpServletResponse response;
//http请求方法
private String requestMethod;
//http请求路径
private String requestPath;
//http响应状态码
private int responseCode;
//请求结果渲染器
private ResultRender resultRender;
public RequestProcessorChain(Iterator<RequestProcessor> iterator, HttpServletRequest req, HttpServletResponse resp) {
this.requestProcessorIterator = iterator;
this.request = req;
this.response = resp;
this.requestMethod = req.getMethod();
this.requestPath = req.getPathInfo();
this.responseCode = HttpServletResponse.SC_OK;
}
/**
* 以责任链的模式执行请求链
*/
public void doRequestProcessorChain() {
//1.通过迭代器遍历注册的请求处理器实现类列表
try{
while(requestProcessorIterator.hasNext()){
//2.直到某个请求处理器执行后返回为false为止
if(!requestProcessorIterator.next().process(this)){
break;
}
}} catch (Exception e){
//3.期间如果出现异常,则交由内部异常渲染器处理
this.resultRender = new InternalErrorResultRender(e.getMessage());
log.error("doRequestProcessorChain error:", e);
}
}
/**
* 执行处理器
*/
public void doRender() {
//1.如果请求处理器实现类均未选择合适的渲染器,则使用默认的
if(this.resultRender == null){
this.resultRender = new DefaultResultRender();
}
//2.调用渲染器的render方法对结果进行渲染
try {
this.resultRender.render(this);
} catch (Exception e) {
log.error("doRender error: ", e);
throw new RuntimeException(e);
}
}
}
4.定义RequestProcessor矩阵
定义处理动作规范
/**
* 请求执行器接口
*/
public interface RequestProcessor {
boolean process(RequestProcessorChain requestProcessorChain) throws Exception;
}
请求预处理器
package org.simplespring.mvc.processor.impl;
import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;
/**
* 请求预处理,包括编码以及路径处理
*/
@Slf4j
public class PreRequestProcessor implements RequestProcessor {
@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
// 1.设置请求编码,将其统一设置成UTF-8
requestProcessorChain.getRequest().setCharacterEncoding("UTF-8");
// 2.将请求路径末尾的/剔除,为后续匹配Controller请求路径做准备
// (一般Controller的处理路径是/aaa/bbb,所以如果传入的路径结尾是/aaa/bbb/,
// 就需要处理成/aaa/bbb)
String requestPath = requestProcessorChain.getRequestPath();
//http://localhost:8080/simpleframework requestPath="/"
if(requestPath.length() > 1 && requestPath.endsWith("/")){
requestProcessorChain.setRequestPath(requestPath.substring(0, requestPath.length() - 1));
}
log.info("preprocess request {} {}", requestProcessorChain.getRequestMethod(), requestProcessorChain.getRequestPath());
return true;
}
}
静态资源请求处理器
package org.simplespring.mvc.processor.impl;
import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
/**
* 静态资源请求处理,包括但不限于图片、css、以及js文件等 - DefaultServlet
*/
@Slf4j
public class StaticResourceRequestProcessor implements RequestProcessor {
public static final String DEFAULT_TOMCAT_SERVLET = "default";
public static final String STATIC_RESOURCE_PREFIX = "/static/";
//tomcat默认请求派发器RequestDispatcher的名称
RequestDispatcher defaultDispatcher;
public StaticResourceRequestProcessor(ServletContext servletContext) {
this.defaultDispatcher = servletContext.getNamedDispatcher(DEFAULT_TOMCAT_SERVLET);
if(this.defaultDispatcher == null){
throw new RuntimeException("There is no default tomcat servlet");
}
log.info("The default servlet for static resource is {}", DEFAULT_TOMCAT_SERVLET);
}
@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
//1.通过请求路径判断是否是请求的静态资源 webapp/static
if(isStaticResource(requestProcessorChain.getRequestPath())){
//2.如果是静态资源,则将请求转发给default servlet处理
defaultDispatcher.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
return false;
}
return true;
}
//通过请求路径前缀(目录)是否为静态资源 /static/
private boolean isStaticResource(String path){
return path.startsWith(STATIC_RESOURCE_PREFIX);
}
}
jsp资源请求处理器
package org.simplespring.mvc.processor.impl;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
/**
* jsp资源请求处理
*/
public class JspRequestProcessor implements RequestProcessor {
//jsp请求的RequestDispatcher的名称
private static final String JSP_SERVLET = "jsp";
//Jsp请求资源路径前缀
private static final String JSP_RESOURCE_PREFIX = "/templates/";
/**
* jsp的RequestDispatcher,处理jsp资源
*/
private RequestDispatcher jspServlet;
public JspRequestProcessor(ServletContext servletContext) {
jspServlet = servletContext.getNamedDispatcher(JSP_SERVLET);
if (null == jspServlet) {
throw new RuntimeException("there is no jsp servlet");
}
}
@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
if (isJspResource(requestProcessorChain.getRequestPath())) {
jspServlet.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
return false;
}
return true;
}
/**
* 是否请求的是jsp资源
*/
private boolean isJspResource(String url) {
return url.startsWith(JSP_RESOURCE_PREFIX);
}
}
Controller请求处理器
package org.simplespring.mvc.processor.impl;
import lombok.extern.slf4j.Slf4j;
import org.simplespring.core.BeanContainer;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.annotation.RequestMapping;
import org.simplespring.mvc.annotation.RequestParam;
import org.simplespring.mvc.annotation.ResponseBody;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.render.JsonResultRender;
import org.simplespring.mvc.render.ResourceNotFoundResultRender;
import org.simplespring.mvc.render.ResultRender;
import org.simplespring.mvc.render.ViewResultRender;
import org.simplespring.mvc.type.ControllerMethod;
import org.simplespring.mvc.type.RequestPathInfo;
import org.simplespring.util.ConverterUtil;
import org.simplespring.util.ValidationUtil;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Controller请求处理器
*/
@Slf4j
public class ControllerRequestProcessor implements RequestProcessor {
//IOC容器
private BeanContainer beanContainer;
//请求和controller方法的映射集合
private Map<RequestPathInfo, ControllerMethod> pathControllerMethodMap = new ConcurrentHashMap<>();
/**
* 依靠容器的能力,建立起请求路径、请求方法与Controller方法实例的映射
*/
public ControllerRequestProcessor() {
this.beanContainer = BeanContainer.getInstance();
Set<Class<?>> requestMappingSet = beanContainer.getClassesByAnnotation(RequestMapping.class);
initPathControllerMethodMap(requestMappingSet);
}
private void initPathControllerMethodMap(Set<Class<?>> requestMappingSet) {
if (ValidationUtil.isEmpty(requestMappingSet)) {
return;
}
//1.遍历所有被@RequestMapping标记的类,获取类上面该注解的属性值作为一级路径
for (Class<?> requestMappingClass : requestMappingSet) {
RequestMapping requestMapping = requestMappingClass.getAnnotation(RequestMapping.class);
String basePath = requestMapping.value();
if (!basePath.startsWith("/")) {
basePath = "/" + basePath;
}
//2.遍历类里所有被@RequestMapping标记的方法,获取方法上面该注解的属性值,作为二级路径
Method[] methods = requestMappingClass.getDeclaredMethods();
if (ValidationUtil.isEmpty(methods)) {
continue;
}
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping methodRequest = method.getAnnotation(RequestMapping.class);
String methodPath = methodRequest.value();
if (!methodPath.startsWith("/")) {
methodPath = "/" + basePath;
}
String url = basePath + methodPath;
//3.解析方法里被@RequestParam标记的参数,
// 获取该注解的属性值,作为参数名,
// 获取被标记的参数的数据类型,建立参数名和参数类型的映射
Map<String, Class<?>> methodParams = new HashMap<>();
Parameter[] parameters = method.getParameters();
if (!ValidationUtil.isEmpty(parameters)) {
for (Parameter parameter : parameters) {
RequestParam param = parameter.getAnnotation(RequestParam.class);
//目前暂定为Controller方法里面所有的参数都需要@RequestParam注解
if (param == null) {
throw new RuntimeException("The parameter must have @RequestParam");
}
methodParams.put(param.value(), parameter.getType());
}
}
//4.将获取到的信息封装成RequestPathInfo实例和ControllerMethod实例,放置到映射表里
String httpMethod = String.valueOf(methodRequest.method());
RequestPathInfo requestPathInfo = new RequestPathInfo(httpMethod, url);
if (this.pathControllerMethodMap.containsKey(requestPathInfo)) {
log.warn("duplicate url:{} registration,current class {} method{} will override the former one",
requestPathInfo.getHttpPath(), requestMappingClass.getName(), method.getName());
}
ControllerMethod controllerMethod = new ControllerMethod(requestMappingClass, method, methodParams);
this.pathControllerMethodMap.put(requestPathInfo, controllerMethod);
}
}
}
}
@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
//1.解析HttpSevletRequest的请求方法,请求路径,获取对应的ControllerMethod实例
String method = requestProcessorChain.getRequestMethod();
String path = requestProcessorChain.getRequestPath();
ControllerMethod controllerMethod = this.pathControllerMethodMap.get(new RequestPathInfo(method, path));
if (controllerMethod == null) {
requestProcessorChain.setResultRender(new ResourceNotFoundResultRender(method, path));
return false;
}
//2.解析请求参数,并传递给获取到的ControllerMethod实例去执行
Object result = invokeControllerMethod(controllerMethod, requestProcessorChain.getRequest());
//3.根据处理的结果,选择对应的render进行渲染
setResultRender(result, controllerMethod, requestProcessorChain);
return true;
}
/**
* 根据不同情况设置不同的渲染器
*/
private void setResultRender(Object result, ControllerMethod controllerMethod, RequestProcessorChain requestProcessorChain) {
if (result == null) {
return;
}
ResultRender resultRender;
boolean isJson = controllerMethod.getInvokeMethod().isAnnotationPresent(ResponseBody.class);
if (isJson) {
resultRender = new JsonResultRender(result);
} else {
resultRender = new ViewResultRender(result);
}
requestProcessorChain.setResultRender(resultRender);
}
private Object invokeControllerMethod(ControllerMethod controllerMethod, HttpServletRequest request) {
//1.从请求里获取GET或者POST的参数名及其对应的值
Map<String, String> requestParamMap = new HashMap<>();
//GET,POST方法的请求参数获取方式
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> parameter : parameterMap.entrySet()
) {
if (!ValidationUtil.isEmpty(parameter.getValue())) {
//只支持一个参数对应一个值的形式
requestParamMap.put(parameter.getKey(), parameter.getValue()[0]);
}
}
//2.根据获取到的请求参数名及其对应的值,以及controllerMethod里面的参数和类型的映射关系,去实例化出方法对应的参数
List<Object> methodParams = new ArrayList<>();
Map<String, Class<?>> methodParamMap = controllerMethod.getMethodParameters();
for (String paramName : methodParamMap.keySet()) {
Class<?> type = methodParamMap.get(paramName);
String requestValue = requestParamMap.get(paramName);
Object value;
//只支持String 以及基础类型char,int,short,byte,double,long,float,boolean,及它们的包装类型
if (requestValue == null) {
//将请求里的参数值转成适配于参数类型的空值
value = ConverterUtil.primitiveNull(type);
} else {
value = ConverterUtil.convert(type, requestValue);
}
methodParams.add(value);
}
//3.执行Controller里面对应的方法并返回结果
Object controller = beanContainer.getBean(controllerMethod.getControllerClass());
Method invokeMethod = controllerMethod.getInvokeMethod();
invokeMethod.setAccessible(true);
Object result;
try {
if (methodParams.size() == 0) {
result = invokeMethod.invoke(controller);
} else {
result = invokeMethod.invoke(controller, methodParams.toArray());
}
} catch (InvocationTargetException e) {
//如果是调用异常的话,需要通过e.getTargetException()
// 去获取执行方法抛出的异常
throw new RuntimeException(e.getTargetException());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return result;
}
}
5.定义Render矩阵
定义渲染动作规范
/**
* 渲染请求结果
*/
public interface ResultRender {
//执行渲染
void render(RequestProcessorChain requestProcessorChain) throws Exception;
}
默认渲染器
/**
* 默认渲染器
*/
public class DefaultResultRender implements ResultRender {
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().setStatus(requestProcessorChain.getResponseCode());
}
}
内部异常渲染器
/**
* 内部异常渲染器
*/
public class InternalErrorResultRender implements ResultRender{
private String errorMsg;
public InternalErrorResultRender(String errorMsg){
this.errorMsg = errorMsg;
}
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
}
}
Json渲染器
package org.simplespring.mvc.render;
import com.google.gson.Gson;
import org.simplespring.mvc.RequestProcessorChain;
import java.io.PrintWriter;
/**
* Json渲染器
*/
public class JsonResultRender implements ResultRender {
private Object jsonData;
public JsonResultRender(Object jsonData) {
this.jsonData = jsonData;
}
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
// 设置响应头
requestProcessorChain.getResponse().setContentType("application/json");
requestProcessorChain.getResponse().setCharacterEncoding("UTF-8");
// 响应流写入经过gson格式化之后的处理结果
try(PrintWriter writer = requestProcessorChain.getResponse().getWriter()){
Gson gson = new Gson();
writer.write(gson.toJson(jsonData));
writer.flush();
}
}
}
资源找不到时使用的渲染器
package org.simplespring.mvc.render;
import org.simplespring.mvc.RequestProcessorChain;
import javax.servlet.http.HttpServletResponse;
/**
* 资源找不到时使用的渲染器
*/
public class ResourceNotFoundResultRender implements ResultRender {
private String httpMethod;
private String httpPath;
public ResourceNotFoundResultRender(String method, String path) {
this.httpMethod = method;
this.httpPath = path;
}
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND,
"获取不到对应的请求资源:请求路径[" + httpPath + "]" + "请求方法[" + httpMethod + "]");
}
}
页面渲染器
package org.simplespring.mvc.render;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.type.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* 页面渲染器
*/
public class ViewResultRender implements ResultRender{
public static final String VIEW_PATH = "/templates/";
private ModelAndView modelAndView;
/**
* 对传入的参数进行处理,并赋值给ModelAndView成员变量
* @param mv
*/
public ViewResultRender(Object mv) {
if(mv instanceof ModelAndView){
//1.如果入参类型是ModelAndView,则直接赋值给成员变量
this.modelAndView = (ModelAndView)mv;
} else if(mv instanceof String){
//2.如果入参类型是String,则为视图,需要包装后才赋值给成员变量
this.modelAndView = new ModelAndView().setView((String)mv);
} else {
//3.针对其他情况,则直接抛出异常
throw new RuntimeException("illegal request result type");
}
}
/**
* 将请求处理结果按照视图路径转发至对应视图进行展示
* @param requestProcessorChain
* @throws Exception
*/
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
HttpServletRequest request = requestProcessorChain.getRequest();
HttpServletResponse response = requestProcessorChain.getResponse();
String path = modelAndView.getView();
Map<String, Object> model = modelAndView.getModel();
for(Map.Entry<String, Object> entry : model.entrySet()){
request.setAttribute(entry.getKey(), entry.getValue());
}
//JSP
request.getRequestDispatcher(VIEW_PATH +path).forward(request, response);
}
}
6.其他数据封装包装类和工具类
/**
* 待执行的Controller及其方法实例和参数的映射
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ControllerMethod {
//Controller对应的Class对象
private Class<?> controllerClass;
//执行的Controller方法实例
private Method invokeMethod;
//方法参数名称以及对应的参数类型
private Map<String, Class<?>> methodParameters;
}
/**
* 存储处理完后的结果数据,以及显示该数据的视图
*/
public class ModelAndView {
//页面所在的路径
@Getter
private String view;
//页面的data数据
@Getter
private Map<String, Object> model = new HashMap<>();
public ModelAndView setView(String view){
this.view = view;
return this;
}
//modelAndView.setView("addheadline.jsp").addViewData("aaa", "bbb");
public ModelAndView addViewData(String attributeName, Object attributeValue){
model.put(attributeName, attributeValue);
return this;
}
}
/**
* 目前支持的请求方法
*/
public enum RequestMethod {
GET,
POST
}
/**
* 存储http请求路径和请求方法
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestPathInfo {
//http请求方法
private String httpMethod;
//http请求路径
private String httpPath;
}
package org.simplespring.util;
public class ConverterUtil {
/**
* 返回基本数据类型的空值
*需要特殊处理的基本类型即intdoubleshortlongytefloatoolean
* @param type 参数类型
* @return 对应的空值
*/
public static Object primitiveNull(Class<?> type) {
if (type == int.class || type == double.class ||
type == short.class || type == long.class ||
type == byte.class || type == float.class) {
return 0;
} else if(type == boolean.class){
return false;
}
return null;
}
/**
* String类型转换成对应的参数类型
*
* @param type 参数类型
* @param requestValue 值
* @return 转换后的Object
*/
public static Object convert(Class<?> type, String requestValue) {
if(isPrimitive(type)){
if(ValidationUtil.isEmpty(requestValue)){
return primitiveNull(type);
}
if (type.equals(int.class) || type.equals(Integer.class)) {
return Integer.parseInt(requestValue);
} else if (type.equals(String.class)) {
return requestValue;
} else if (type.equals(Double.class) || type.equals(double.class)) {
return Double.parseDouble(requestValue);
} else if (type.equals(Float.class) || type.equals(float.class)) {
return Float.parseFloat(requestValue);
} else if (type.equals(Long.class) || type.equals(long.class)) {
return Long.parseLong(requestValue);
} else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
return Boolean.parseBoolean(requestValue);
} else if (type.equals(Short.class) || type.equals(short.class)) {
return Short.parseShort(requestValue);
} else if (type.equals(Byte.class) || type.equals(byte.class)) {
return Byte.parseByte(requestValue);
}
return requestValue;
} else {
throw new RuntimeException("count not support non primitive type conversion yet");
}
}
/**
* 判定是否基本数据类型(包括包装类以及String)
*
* @param type 参数类型
* @return 是否为基本数据类型
*/
private static boolean isPrimitive(Class<?> type) {
return type == boolean.class
|| type == Boolean.class
|| type == double.class
|| type == Double.class
|| type == float.class
|| type == Float.class
|| type == short.class
|| type == Short.class
|| type == int.class
|| type == Integer.class
|| type == long.class
|| type == Long.class
|| type == String.class
|| type == byte.class
|| type == Byte.class
|| type == char.class
|| type == Character.class;
}
}
总结一下大致流程:
1.定义配置标记
1.@RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系
2.@RequestParam:请求的方法参数名称
3.@ResponseBody:用于标记自动对返回值进行json处理
2.转发控制器
核心流程:
1.初始化
- 1.初始化容器
- 2.doAop
- 3.doIoc
- 4.初始化请求处理器责任链
2.处理请求
-
1.创建责任链对象实例
-
2.通过责任链模式来依次调用请求处理器对请求进行处理
-
3.对处理结果进行渲染
3.请求处理责任链
1.以责任链的模式执行注册的请求处理器
2.委派给特定的Render实例对处理后的结果进行渲染
4.定义RequestProcessor矩阵
请求预处理器/静态资源请求处理器/jsp资源请求处理器/Controller请求处理器
5.定义Render矩阵
默认渲染器/内部异常渲染器/Json渲染器/资源找不到时使用的渲染器/页面渲染器/
6.其他数据封装包装类和工具类