自己实现一个简易的SpringMVC
2017-05-17 10:13
489 查看
上回实现了一个简易的Spring,那就顺便实现一些SpringMVC吧。由于有了上回的基础,这回实现比较快,晚饭前架构了一下,一晚上就写得差不多了。自己实现的架构比较简单,下面简单介绍一下。
源码下载:http://download.csdn.net/detail/jobsandczj/9844308
实现思路及工作流程:
定义一个DispatcherServlet,用来做请求入口。初始化时,去读取配置文件,获得Controller的包,然后“注入”Controller。SpringMVC它本身是有自己的IoC容器的,用来注入Controller以及它的组件,但IoC我在Spring里玩过了,这回就没有写依赖注入。但完事后发现其实也没省多少功夫,终归还是要扫包,解析的。
得到Controller后就构建Handler。让每个Handler与一个请求路径对应,我只定义了两种类型的Handler,一个是处理页面转发的,一个是返回Json数据的。每种Handler都有它的适配器,这就让Controller的方法设置参数少了很多约束,只要是request,response,session这仨家伙就行。
最后初始化适配器列表,以便在接收到请求后适配。
下面是Handler抽象类:
下面这个是操作工具类,进行方法参数适配和适配器列表初始化
package MySpringMVC.springmvc;
import MySpringMVC.utils.OperationUtil;
import MySpringMVC.utils.PropertiesReaderUtil;
import MySpringMVC.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by 10033 on 2017/5/16.
*/
public class DispatcherServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
private String configName;
private Map<String, String> configMap;
private static final String SCAN_PACK="scan.package";
private static final String VIEWPATH_STATIC="viewpath.static";
private HandlerMap handleMap;
private List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
//初始化
public void init(String configName) throws ServletException {
super.init();
// configName=getInitParameter("contextConfigLocationName");
configMap= PropertiesReaderUtil.getProperties(configName);
String packages=configMap.get(SCAN_PACK);//获得扫描包
DispatchHelper.setMap(configMap);
try {
List<String> list=new ClasspathPackageScanner(packages).getFullyQualifiedClassNameList();
handleMap=new HandlerMap(list);
} catch (IOException e) {
logger.error(e.getMessage());
}
OperationUtil.initHandlerAdapterList(handlerAdapters);
}
@Override
public void init(ServletConfig config) throws ServletException {
init(config.getInitParameter("contextConfigLocationName"));
ServletContext servletContext=config.getServletContext();
/*ServletRegistration servletRegistration = servletContext.getServletRegistration("jsp");
servletRegistration.addMapping("/WEB-INF/jsps*//*");*/
ServletRegistration servletRegistration2 = servletContext.getServletRegistration("default");
String[] staticString=configMap.get(VIEWPATH_STATIC).split(";");
for(int i=0;i<staticString.length;i++) {
servletRegistration2.addMapping(staticString[i].toLowerCase()+"/*");
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求路径
String requestUrl=StringUtil.getRequestURL(req);
Handler handler=handleMap.getHandler(requestUrl,req.getMethod());
if(null!=handler) {
for(HandlerAdapter handlerAdapter:handlerAdapters) {
if(handlerAdapter.support(handler)) {
handlerAdapter.setHandler(handler);
handlerAdapter.execute(req,resp);
break;
}
}
}else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
}
这回还是有一些不足的,一是没实现IoC,当然这是自己偷懒。但还有一个不足就是,由于前端只支持JSP,所以View,Model这些也都没管。
源码下载:http://download.csdn.net/detail/jobsandczj/9844308
实现思路及工作流程:
定义一个DispatcherServlet,用来做请求入口。初始化时,去读取配置文件,获得Controller的包,然后“注入”Controller。SpringMVC它本身是有自己的IoC容器的,用来注入Controller以及它的组件,但IoC我在Spring里玩过了,这回就没有写依赖注入。但完事后发现其实也没省多少功夫,终归还是要扫包,解析的。
得到Controller后就构建Handler。让每个Handler与一个请求路径对应,我只定义了两种类型的Handler,一个是处理页面转发的,一个是返回Json数据的。每种Handler都有它的适配器,这就让Controller的方法设置参数少了很多约束,只要是request,response,session这仨家伙就行。
最后初始化适配器列表,以便在接收到请求后适配。
下面是Handler抽象类:
package MySpringMVC.springmvc; import java.lang.reflect.Method; /** * Created by 10033 on 2017/5/16. */ public abstract class Handler { protected Method method; protected Object controller; protected Class[] params; protected RequestMethod requestMethod; public Handler(Method method, Object controller, Class[] params, RequestMethod requestMethod) { this.method = method; this.controller = controller; this.params = params; this.requestMethod = requestMethod; } public Method getMethod() { return method; } public void setMethod(Method method) { this.method = method; } public Object getController() { return controller; } public void setController(Object controller) { this.controller = controller; } public Class[] getParams() { return params; } public void setParams(Class[] params) { this.params = params; } public RequestMethod getRequestMethod() { return requestMethod; } public void setRequestMethod(RequestMethod requestMethod) { this.requestMethod = requestMethod; } }
下面这个是操作工具类,进行方法参数适配和适配器列表初始化
package MySpringMVC.utils; import MySpringMVC.springmvc.ClasspathPackageScanner; import MySpringMVC.springmvc.HandlerAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.List; /** * Created by 10033 on 2017/5/16. */ public class OperationUtil { private static final Logger logger = LoggerFactory.getLogger(OperationUtil.class); private static final String ADAPTER_PACKAGE="MySpringMVC.springmvc"; public static int makeObjectsByClasses (Class[] classes, Object[] objects, HttpServletRequest request, HttpServletResponse response) throws Exception { int cou=0; for(Class cla:classes) { if(cla==HttpServletRequest.class) { objects[cou++]=request; } else if(cla==HttpServletResponse.class) { objects[cou++]=response; } else if(cla==HttpSession.class) { objects[cou++]=request.getSession(); } else { throw new Exception("控制器参数错误"); } } return cou; } public static void initHandlerAdapterList(List<HandlerAdapter> list) { try { List<String> classStringList=new ClasspathPackageScanner(ADAPTER_PACKAGE).getFullyQualifiedClassNameList(); for(String s:classStringList) { Class cla=Class.forName(s); //实现了HandlerAdapter接口 if (HandlerAdapter.class.isAssignableFrom(cla)) { Object obj=cla.newInstance(); list.add((HandlerAdapter) obj); } } } catch (IOException e) { logger.error(e.getMessage()); } catch (ClassNotFoundException e) { logger.error(e.getMessage()); } catch (IllegalAccessException e) { logger.error(e.getMessage()); } catch (InstantiationException e) { logger.error(e.getMessage()); } } }这是DispatcherServlet类,进行初始化和控制器调度,为了管理静态资源要进行servlet注册。
package MySpringMVC.springmvc;
import MySpringMVC.utils.OperationUtil;
import MySpringMVC.utils.PropertiesReaderUtil;
import MySpringMVC.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by 10033 on 2017/5/16.
*/
public class DispatcherServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
private String configName;
private Map<String, String> configMap;
private static final String SCAN_PACK="scan.package";
private static final String VIEWPATH_STATIC="viewpath.static";
private HandlerMap handleMap;
private List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
//初始化
public void init(String configName) throws ServletException {
super.init();
// configName=getInitParameter("contextConfigLocationName");
configMap= PropertiesReaderUtil.getProperties(configName);
String packages=configMap.get(SCAN_PACK);//获得扫描包
DispatchHelper.setMap(configMap);
try {
List<String> list=new ClasspathPackageScanner(packages).getFullyQualifiedClassNameList();
handleMap=new HandlerMap(list);
} catch (IOException e) {
logger.error(e.getMessage());
}
OperationUtil.initHandlerAdapterList(handlerAdapters);
}
@Override
public void init(ServletConfig config) throws ServletException {
init(config.getInitParameter("contextConfigLocationName"));
ServletContext servletContext=config.getServletContext();
/*ServletRegistration servletRegistration = servletContext.getServletRegistration("jsp");
servletRegistration.addMapping("/WEB-INF/jsps*//*");*/
ServletRegistration servletRegistration2 = servletContext.getServletRegistration("default");
String[] staticString=configMap.get(VIEWPATH_STATIC).split(";");
for(int i=0;i<staticString.length;i++) {
servletRegistration2.addMapping(staticString[i].toLowerCase()+"/*");
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求路径
String requestUrl=StringUtil.getRequestURL(req);
Handler handler=handleMap.getHandler(requestUrl,req.getMethod());
if(null!=handler) {
for(HandlerAdapter handlerAdapter:handlerAdapters) {
if(handlerAdapter.support(handler)) {
handlerAdapter.setHandler(handler);
handlerAdapter.execute(req,resp);
break;
}
}
}else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
}
这回还是有一些不足的,一是没实现IoC,当然这是自己偷懒。但还有一个不足就是,由于前端只支持JSP,所以View,Model这些也都没管。
相关文章推荐
- 根据数组的原理,自己实现一个简易版的ArrayList
- 自己来实现一个简易的OCR
- 手动实现一个简易版SpringMvc
- 根据链表的原理,自己实现一个简易版的LinkedList
- 源码分析之动手实现手写一个自己的SpringMVC框架(三)
- 利用HashMap,自己实现一个简易版的HashSet
- 合格前端系列第三弹-实现一个属于我们自己的简易MVVM库
- 根据数组+链表的原理,自己实现一个简易版的HashMap
- 自己实现一个简易web服务器
- 实现一个简易的IoC框架(上)(此篇与Spring.NET无关,为自己手写IoC框架)
- 实现一个简易的IoC框架(上)(此篇与Spring.NET无关,为自己手写IoC框架)
- 自己实现的一个简易Spring框架(IoC+AOP)
- Spring.NET学习笔记3——实现一个简易的IoC框架(练习篇) Level 100
- 自己写一个通用的MessageBox(SDK实现)
- 以注解的形式来实现一个springmvc的简单范例
- Objective-C如何自己实现一个基于数组下标的属性访问模式
- 写出一个你自己的MVC框架-基于对springMVC源码实现和理解(1):入口所在
- 写出一个你自己的MVC框架-基于对springMVC源码实现和理解(2):数据初始化(一)
- --------------------------------开始动手自己写一个简易的操作系统-----------------------------------------0
- 用程序来控制一个网页,实现自己主动输入等操作