自己动手写一个spring之MVC_1
写在前面
本文看下如何定义MVC部分内容。
1:正文
首先定义requestmapping注解,映射url->处理方法:
@Target(value={ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public@interfaceRequestMapping{Stringvalue()default"";}简单期间,这里暂时只支持用在方法上,spring mvc是支持同时用在类和方法上的,知道即可。接着我们还要定义DispatcherServlet作为拦截web请求的入口(只保留核心代码):
// com.hc.minispring.web.v2.DispatcherServletpublicclassDispatcherServletextendsHttpServlet{@Overridepublicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);sContextConfigLocation=config.getInitParameter("contextConfigLocation");URLxmlPath=null;try{xmlPath=this.getServletContext().getResource(sContextConfigLocation);}catch(MalformedURLExceptione){e.printStackTrace();}// 获取所有要扫描的包this.packageNames=XmlScanComponentHelper.getNodeValue(xmlPath);// 刷新beanRefresh();}protectedvoidRefresh(){// 扫描包,获取所有的controller 实例initController();// 初始化url和对应method的映射initMapping();}protectedvoidinitController(){this.controllerNames=scanPackages(this.packageNames);for(StringcontrollerName:this.controllerNames){Objectobj=null;Class<?>clz=null;try{clz=Class.forName(controllerName);this.controllerClasses.put(controllerName,clz);}catch(ClassNotFoundExceptione){e.printStackTrace();}try{obj=clz.newInstance();this.controllerObjs.put(controllerName,obj);}catch(InstantiationExceptione){e.printStackTrace();}catch(IllegalAccessExceptione){e.printStackTrace();}}}protectedvoidinitMapping(){for(StringcontrollerName:this.controllerNames){// ...if(methods!=null){for(Methodmethod:methods){// 判断方法上是否使用了@RequestMapping注解,使用了则获取映射的url,以及对应的方法,存储备用booleanisRequestMapping=method.isAnnotationPresent(RequestMapping.class);if(isRequestMapping){StringmethodName=method.getName();Stringurlmapping=method.getAnnotation(RequestMapping.class).value();// ...// 存储请求web路径和处理该web路径的方法,将会在doGet方法中使用this.mappingMethods.put(urlmapping,method);}}}}}protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{StringsPath=request.getServletPath();// ...try{// 根据请求路径获取处理方法,反射执行,并返回结果Methodmethod=this.mappingMethods.get(sPath);obj=this.mappingObjs.get(sPath);objResult=method.invoke(obj);}catch(SecurityExceptione){// ...}response.getWriter().append(objResult.toString());}}配置component-scan的配置文件如下:
<?xml version="1.0" encoding="UTF-8" ?><components><component-scanbase-package="com.hc.minispring.web.v2.test"/></components>在com.hc.minispring.web.v2.test包中我配置了两个类:
publicclassHelloWorldBean{@RequestMapping("/test")publicStringdoTest(){return"hello world for doGet!";}}publicclassHelloWorldBean1{@RequestMapping("/test1")publicStringdoTest(){return"1hello world for doGet!";}}最后配置下web.xml就行了:
<?xml version="1.0" encoding="UTF-8"?><web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:web="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"id="WebApp_ID"><servlet><servlet-name>minisMVC</servlet-name><servlet-class>com.hc.minispring.web.v2.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/v2/minisMVC-servletv2.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>minisMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>启动后访问:
C:\Users\dell9020>curl http://localhost:8080/minispring_Web_exploded/test hello world for doGet! C:\Users\dell9020>curl http://localhost:8080/minispring_Web_exploded/test1 1hello world for doGet! C:\Users\dell9020>这样一个简单的mini springmvc就完成了。这样,应用程序开发人员就不需要关心servlet啥的了,只需要提供一个类似于/WEB-INF/v2/minisMVC-servletv2.xml的配置文件,然后在自定义的component scan路径下写对应的业务代码就可以了。
写在后面
参考文章列表
手把手带你写一个 MiniSpring 。
