文章目录 1.环境配置 1.创建maven项目 2.创建文件目录 3.导入jar包 2.开发核心控制器 文件目录 1.流程图 2.编写核心控制器SunDispatcherServlet.java 3.类路径下编写spring配置文件sunspringmvc.xml 4.配置中央控制器web.xml 5.配置tomcat,完成测试 1.配置发布方式 2.配置热加载 3.修改SunDispatcherServlet.java 4.完成测试 3.完成客户端/浏览器可以请求控制层 文件目录 1.思路分析 2.编写MonsterController.java 3.自定义注解 1.Controller.java 2.RequestMapping.java 4.自定义容器(1),在tomcat启动时读取配置文件,获取要扫描的包的工作路径 1.SunWebApplicationContext.java 2.修改SunDispatcherServlet.java 3.单元测试,启动tomcat 5.自定义容器(2),在tomcat启动的时候完成对指定包的扫描 1.修改SunWebApplicationContext.java 2.debug测试 6.将自定义容器(3),符合要求的类反射创建对象,放到单例池 1.修改SunWebApplicationContext.java增加方法,添加属性 2.debug查看单例池 7.完成url和控制器方法映射 1.创建映射bean,SunHandler.java 2.修改中央控制器SunWebApplicationContext.java添加方法和属性 3.debug查看映射对象列表 8.完成请求分发到目标方法 1.修改SunDispatcherServlet.java,添加两个方法并在dopost中请求分发 2.单元测试 4.当前阶段完成的功能
1.环境配置
1.创建maven项目
2.创建文件目录
3.导入jar包
< project xmlns = " http://maven.apache.org/POM/4.0.0" xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance" xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > < modelVersion> 4.0.0</ modelVersion> < groupId> org.example</ groupId> < artifactId> sun-springmvc</ artifactId> < packaging> war</ packaging> < version> 1.0-SNAPSHOT</ version> < name> sun-springmvc Maven Webapp</ name> < url> http://maven.apache.org</ url> < dependencies> < dependency> < groupId> junit</ groupId> < artifactId> junit</ artifactId> < version> 3.8.1</ version> < scope> test</ scope> </ dependency> < dependency> < groupId> javax.servlet</ groupId> < artifactId> javax.servlet-api</ artifactId> < version> 3.1.0</ version> < scope> provided</ scope> </ dependency> < dependency> < groupId> dom4j</ groupId> < artifactId> dom4j</ artifactId> < version> 1.6.1</ version> </ dependency> < dependency> < groupId> org.apache.commons</ groupId> < artifactId> commons-lang3</ artifactId> < version> 3.5</ version> </ dependency> </ dependencies> < build> < finalName> sun-springmvc</ finalName> </ build>
</ project>
2.开发核心控制器
文件目录
1.流程图
2.编写核心控制器SunDispatcherServlet.java
package com. Sun . sunspringmvc. servlet; import javax. servlet. ServletException ;
import javax. servlet. http. HttpServlet ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import java. io. IOException ;
public class SunDispatcherServlet extends HttpServlet { @Override protected void doGet ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { super . doGet ( req, resp) ; } @Override protected void doPost ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { super . doPost ( req, resp) ; }
}
3.类路径下编写spring配置文件sunspringmvc.xml
4.配置中央控制器web.xml
<! DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > < web-app> < display-name> Archetype Created Web Application</ display-name> < servlet> < servlet-name> SunDispatcherServlet</ servlet-name> < servlet-class> com.Sun.sunspringmvc.servlet.SunDispatcherServlet</ servlet-class> < init-param> < param-name> contextConfigLocation</ param-name> < param-value> classpath:sunspringmvc.xml</ param-value> </ init-param> < load-on-startup> 1</ load-on-startup> </ servlet> < servlet-mapping> < servlet-name> SunDispatcherServlet</ servlet-name> < url-pattern> /</ url-pattern> </ servlet-mapping> </ web-app>
5.配置tomcat,完成测试
1.配置发布方式
2.配置热加载
3.修改SunDispatcherServlet.java
4.完成测试
3.完成客户端/浏览器可以请求控制层
文件目录
1.思路分析
2.编写MonsterController.java
package com. Sun . controller; import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import java. io. IOException ;
import java. io. PrintWriter ;
public class MonsterController { public void listMonster ( HttpServletRequest request, HttpServletResponse response) { response. setContentType ( "text/html;charset=utf-8" ) ; try { PrintWriter writer = response. getWriter ( ) ; writer. write ( "<h1>妖怪列表信息</h1>" ) ; } catch ( IOException e) { throw new RuntimeException ( e) ; } }
}
3.自定义注解
1.Controller.java
package com. Sun . sunspringmvc. annotation; import java. lang. annotation. * ;
@Target ( ElementType . TYPE )
@Retention ( RetentionPolicy . RUNTIME )
@Documented
public @interface Controller {
}
2.RequestMapping.java
package com. Sun . sunspringmvc. annotation; import java. lang. annotation. * ;
@Target ( ElementType . METHOD )
@Retention ( RetentionPolicy . RUNTIME )
@Documented
public @interface RequestMapping {
}
4.自定义容器(1),在tomcat启动时读取配置文件,获取要扫描的包的工作路径
1.SunWebApplicationContext.java
package com. Sun . sunspringmvc. context; import com. Sun . sunspringmvc. xml. XmlParser; import java. net. URL ;
import java. util. ArrayList ;
import java. util. List ;
public class SunWebApplicationContext { private List < String > classFullPathList = new ArrayList < String > ( ) ; public void init ( ) { String basePage = XmlParser . getBasePage ( "sunspringmvc.xml" ) ; scanPage ( basePage) ; } public void scanPage ( String packFullName) { String packPath = packFullName. replaceAll ( "\\." , "/" ) ; URL resource = SunWebApplicationContext . class . getClassLoader ( ) . getResource ( packPath) ; System . out. println ( resource) ; }
}
2.修改SunDispatcherServlet.java
package com. Sun . sunspringmvc. servlet; import com. Sun . sunspringmvc. context. SunWebApplicationContext; import javax. servlet. ServletConfig ;
import javax. servlet. ServletException ;
import javax. servlet. http. HttpServlet ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import java. io. IOException ;
public class SunDispatcherServlet extends HttpServlet { @Override public void init ( ServletConfig config) throws ServletException { SunWebApplicationContext sunWebApplicationContext = new SunWebApplicationContext ( ) ; sunWebApplicationContext. init ( ) ; } @Override protected void doGet ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { System . out. println ( "doGet" ) ; } @Override protected void doPost ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { System . out. println ( "doPost" ) ; }
}
3.单元测试,启动tomcat
5.自定义容器(2),在tomcat启动的时候完成对指定包的扫描
1.修改SunWebApplicationContext.java
package com. Sun . sunspringmvc. context; import com. Sun . sunspringmvc. xml. XmlParser; import java. io. File ;
import java. net. URL ;
import java. util. ArrayList ;
import java. util. List ;
public class SunWebApplicationContext { private List < String > classFullPathList = new ArrayList < String > ( ) ; public void init ( ) { String basePage = XmlParser . getBasePage ( "sunspringmvc.xml" ) ; String [ ] split = basePage. split ( "," ) ; for ( String packPath : split) { scanPage ( packPath) ; } } public void scanPage ( String packFullName) { String packPath = packFullName. replaceAll ( "\\." , "/" ) ; URL url = SunWebApplicationContext . class . getClassLoader ( ) . getResource ( packPath) ; String file = url. getFile ( ) ; File packDirectory = new File ( file) ; if ( packDirectory. isDirectory ( ) ) { File [ ] files = packDirectory. listFiles ( ) ; for ( File classFile : files) { if ( classFile. isDirectory ( ) ) { scanPage ( packFullName + "." + classFile. getName ( ) ) ; } else { String classFullPath = packFullName + "." + classFile. getName ( ) . replaceAll ( ".class" , "" ) ; classFullPathList. add ( classFullPath) ; } } } } }
2.debug测试
6.将自定义容器(3),符合要求的类反射创建对象,放到单例池
1.修改SunWebApplicationContext.java增加方法,添加属性
public void executeInstance ( ) { for ( String classPath : classFullPathList) { try { Class < ? > aClass = Class . forName ( classPath) ; if ( aClass. isAnnotationPresent ( Controller . class ) ) { String name = aClass. getSimpleName ( ) . substring ( 0 , 1 ) . toLowerCase ( ) + aClass. getSimpleName ( ) . substring ( 1 ) ; singleObjects. put ( name, aClass. newInstance ( ) ) ; } } catch ( ClassNotFoundException e) { throw new RuntimeException ( e) ; } catch ( InstantiationException e) { throw new RuntimeException ( e) ; } catch ( IllegalAccessException e) { throw new RuntimeException ( e) ; } } }
2.debug查看单例池
7.完成url和控制器方法映射
1.创建映射bean,SunHandler.java
package com. Sun . sunspringmvc. handler; import java. lang. reflect. Method ;
public class SunHandler { private String url; private Object controller; private Method method; public SunHandler ( String url, Object controller, Method method) { this . url = url; this . controller = controller; this . method = method; } public String getUrl ( ) { return url; } public void setUrl ( String url) { this . url = url; } public Object getController ( ) { return controller; } public void setController ( Object controller) { this . controller = controller; } public Method getMethod ( ) { return method; } public void setMethod ( Method method) { this . method = method; } @Override public String toString ( ) { return "SunHandler{" + "url='" + url + '\'' + ", controller=" + controller + ", method=" + method + '}' ; }
}
2.修改中央控制器SunWebApplicationContext.java添加方法和属性
private void initHandlerMapping ( ) { if ( sunWebApplicationContext. singleObjects. isEmpty ( ) ) { return ; } for ( Map. Entry < String , Object > entry : sunWebApplicationContext. singleObjects. entrySet ( ) ) { Class < ? > aClass = entry. getValue ( ) . getClass ( ) ; if ( aClass. isAnnotationPresent ( Controller . class ) ) { Method [ ] declaredMethods = aClass. getDeclaredMethods ( ) ; for ( Method declaredMethod : declaredMethods) { if ( declaredMethod. isAnnotationPresent ( RequestMapping . class ) ) { String url = declaredMethod. getAnnotation ( RequestMapping . class ) . value ( ) ; SunHandler sunHandler = new SunHandler ( url, entry. getValue ( ) , declaredMethod) ; handlers. add ( sunHandler) ; } } } } }
3.debug查看映射对象列表
8.完成请求分发到目标方法
1.修改SunDispatcherServlet.java,添加两个方法并在dopost中请求分发
package com. Sun . sunspringmvc. servlet; import com. Sun . sunspringmvc. annotation. Controller;
import com. Sun . sunspringmvc. annotation. RequestMapping;
import com. Sun . sunspringmvc. context. SunWebApplicationContext;
import com. Sun . sunspringmvc. handler. SunHandler; import javax. servlet. ServletConfig ;
import javax. servlet. ServletException ;
import javax. servlet. http. HttpServlet ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import java. io. IOException ;
import java. lang. reflect. InvocationTargetException ;
import java. lang. reflect. Method ;
import java. util. ArrayList ;
import java. util. List ;
import java. util. Map ;
public class SunDispatcherServlet extends HttpServlet { private List < SunHandler > handlers = new ArrayList < SunHandler > ( ) ; private SunWebApplicationContext sunWebApplicationContext = null ; @Override public void init ( ServletConfig config) throws ServletException { sunWebApplicationContext = new SunWebApplicationContext ( ) ; sunWebApplicationContext. init ( ) ; initHandlerMapping ( ) ; System . out. println ( "ss" ) ; } @Override protected void doGet ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { doPost ( req, resp) ; } @Override protected void doPost ( HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { executeDispatch ( req, resp) ; } private void initHandlerMapping ( ) { if ( sunWebApplicationContext. singleObjects. isEmpty ( ) ) { return ; } for ( Map. Entry < String , Object > entry : sunWebApplicationContext. singleObjects. entrySet ( ) ) { Class < ? > aClass = entry. getValue ( ) . getClass ( ) ; if ( aClass. isAnnotationPresent ( Controller . class ) ) { Method [ ] declaredMethods = aClass. getDeclaredMethods ( ) ; for ( Method declaredMethod : declaredMethods) { if ( declaredMethod. isAnnotationPresent ( RequestMapping . class ) ) { String url = declaredMethod. getAnnotation ( RequestMapping . class ) . value ( ) ; SunHandler sunHandler = new SunHandler ( url, entry. getValue ( ) , declaredMethod) ; handlers. add ( sunHandler) ; } } } } } private SunHandler getSunHandler ( HttpServletRequest request) { String requestURI = request. getRequestURI ( ) ; String contextPath = request. getServletContext ( ) . getContextPath ( ) ; for ( SunHandler handler : handlers) { if ( ( contextPath + "/" + handler. getUrl ( ) ) . equals ( requestURI) ) { return handler; } } return null ; } private void executeDispatch ( HttpServletRequest request, HttpServletResponse response) { SunHandler sunHandler = getSunHandler ( request) ; if ( sunHandler != null ) { try { sunHandler. getMethod ( ) . invoke ( sunHandler. getController ( ) , request, response) ; } catch ( IllegalAccessException e) { throw new RuntimeException ( e) ; } catch ( InvocationTargetException e) { throw new RuntimeException ( e) ; } } else { try { response. getWriter ( ) . write ( "<h1>404 not found!</h1>" ) ; } catch ( IOException e) { throw new RuntimeException ( e) ; } } }
}
2.单元测试
4.当前阶段完成的功能
1.初始化阶段
tomcat服务器启动,自动装载中央控制器(servlet),调用init方法 初始化spring容器 创建spring容器实例,调用init方法 读取spring配置文件,得到要扫描的包的工作路径 扫描指定的包,获取所有class文件的全路径 扫描所有class文件,将包含Controller注解的类反射创建对象放到单例池中(这里假设都是单例的) 初始化映射对象列表 扫描所有单例池中的对象 反射获取这个对象对应类的所有方法,如果方法包含RequestMapping注解,则将这个对象,url,Method对象封装到映射对象中,并且添加到映射对象列表
2.完成请求分发
根据请求对象得到映射对象 获取请求的uri 遍历对象映射列表查看是否有匹配的映射对象,如果有则返回映射对象 请求分发 首先根据请求对象得到映射对象 如果得到了就反射调用方法 没有得到则返回404