从零开始写javaweb框架 (2)
在本节实现网页请求框架实现的整个过程,在本节中我们就能完美理解Spring到底为我们做了多少事情。
首先来讲一下在JAVAWEB框架中最重要的类DispatcherServlet,即请求转发器。Spring框架是在Servlet基础上进行改进的,因此我们的请求转发类也同样要继承HttpServlet类,重新父类中的初始化方法,完成对上一节讲述的Helper类进行初始化、获取ServletContext对象、注册处理JSP的Servlet、jsp映射路径、注册处理静态资源的默认Servlet等
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//初始化相关Helper类
HelperLoader.init();
//获取ServletContext对象(用于注册Servlet)
ServletContext servletContext = servletConfig.getServletContext();
//注册处理JSP的Servlet
ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
//jsp映射路径
jspServlet.addMapping(ConfigHelper.getAppJspPath()+"*");
//注册处理静态资源的默认Servlet
ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
defaultServlet.addMapping(ConfigHelper.getAppJspPath()+"*");
}
第二步就是重写父类中service方法,这个就是我们框架中最重要的方法了。
- 获取请求方法与请求路径
String requestMethod = req.getMethod().toLowerCase();
String requestPath = req.getPathInfo();
- 获取Action处理器
Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
public static Handler getHandler(String requestMethod,String requestPath){
Request request = new Request(requestMethod,requestPath);
return ACTION_MAP.get(request);
}
从ControllerHelper中获取相对应的处理方法。在这里有个特别需要注意的点:
在获取处理方法的过程中将请求方法和请求路径封装在Request请求中,因此我们不能直接从ACTION_MAP中获取,因为ACTION_MAP是hashMap结构,判断是否相等时对比的是地址,因此我们需要重写Request的hashcode和equals方法。
3.获取Controller类及其Bean实例
4.创建请求参数对象,参数对象分为两个部分post提交的参数、Url中携带的参数
//post提交的参数
Enumeration<String> parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()){
String paramName = parameterNames.nextElement();
String paramValue = req.getParameter(paramName);
paramMap.put(paramName, paramValue);
}
/从url中获取参数,&分割
String body = CodecUtil.decodeURL(StreamUtil.getString(req.getInputStream()));
if(StringUtil.isNotEmpty(body)){
String[] params = StringUtil.splitString(body, "&");
if(ArrayUtil.isNotEmpty(params)){
for(String param : params){
String[] array = StringUtil.splitString(param, "=");
if(ArrayUtil.isNotEmpty(array)){
String paramName = array[0];
String paramValue = array[1];
paramMap.put(paramName, paramValue);
}
}
}
}
5.调用Action方法
6.处理Action返回值,判断返回值是视图还是JSON数据
if(result instanceof View){
//返回JSP
View view = (View) result;
String path = view.getPath();
if(StringUtil.isNotEmpty(path)){
if(path.startsWith("/")){
res.sendRedirect(req.getContextPath()+path);
}else{
Map<String, Object> model = view.getModel();
for(Map.Entry<String, Object>entry:model.entrySet()){
req.setAttribute(entry.getKey(), entry.getValue());
}
req.getRequestDispatcher(ConfigHelper.getAppJspPath()+path).forward(req, res);
}
}
}else if(result instanceof Data){
//返回JSON数据
Data data = (Data) result;
Object model = data.getModel();
if(model != null){
res.setContentType("application/json");
res.setCharacterEncoding("UTF-8");
PrintWriter writer = res.getWriter();
String json = JsonUtil.toJson(model);
writer.write(json);
writer.flush();
writer.close();
}
}
如此我们就完成了最简单的JAVAWEB的框架了,目前该框架拥有依赖注入、方法层面的请求调用、注解配置等功能。下一节我们将来讲讲Spring中另一个最重要的特性--AOP。