文章目录
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