源码地址
1.创建web项目,使用Maven管理项目
2.导入servlet-api jar包
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
3.创建SpringMVC使用的一些常用的注解类
注解 | 功能说明 |
---|---|
RogerResource | 使用方法,只能使用在类的成员变量上 根据名称或者成员变量的名称依赖注入实例到对象中去 |
RogerController | 使用方法,只能使用在类上 标记此类是个控制层 |
RogerService | 使用方法,只能使用在类上 标记此类是个服务层,即业务层 |
RogerRequestMapping | 使用方法,既能作用在类上,也能作用在方法上 值是url映射路径 |
RogerRequestParam | 使用方法,只能作用在方法的参数上 值是从前台web浏览器传递过来的参数值 |
4.创建一些使用这些注解的服务类和控制层的类
5.创建SpringMVC核心类RogerDispatcherSevlet
//1 加载属性文件
//2 根据包名扫描项目中所有的class文件
// 这里通过properties文件获取
// 2.1 获取项目编译后的统一资源定位符
// 2.2 根据统一资源定位符,获取当前目录文件
// 2.3 获取当前目录下的所有文件信息
// 2.4 遍历当前目录文件下的文件信息
// 如果文件类型是目录,则递归调用扫描包的方法
// 如果文件类型是文件,则添加到文件存储容器中去
//3 根据(1)获取到的class文件全路径,
// 实例化具有注解配置的class,并放入IOC容器
//4 依赖注入
// 把实例化的对象注入到相应的实例化对象中的成员变量
//5 初始化url和method映射关系
//6 实际进行调用controller的方法
//6.1 获取实际请求的url
//6.2 获取url映射的方法
//6.3 获取方法的控制类,即方法是不能单独存在的,方法是属于某个类的
//6.4 获取执行方法所需的参数
//6.4.1获取参数列表类型
//6.5 反射调用方法
6.配置web.xml文件,应用启动的时候加载核心Servlet
<!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>SpringMVC by MySelf</display-name>
<servlet>
<servlet-name>RogerDispatcherServlet</servlet-name>
<servlet-class>com.roger.servlet.RogerDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>application.properties</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RogerDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<load-on-startup> | 作用以及说明 |
---|---|
1.是否在web应用程序启动的时候,加载这个Servlet,即实例化并调用其init()方法 | |
2.值必须是一个整数,表示servlet加载的顺序 | |
3.当值为负数或者没有设置,则容器会当servlet被请求时再加载 | |
4.如果为正数,或者0时,表示容器启动的时候就加载并初始化这个servlet,值越小,优先级越高 |
说明:参数解析有两种实现方式
1.简单的方式
Class<?>[] argTypes = method.getParameterTypes();
Object[] args = new Object[argTypes.length];
int i = 0;
for(Class argType : argTypes){
String argClassName = argType.getSimpleName();
if(ServletRequest.class.isAssignableFrom(argType)){
args[i++] = req;
}else if(ServletResponse.class.isAssignableFrom(argType)){
args[i++] = resp;
}else{
Annotation[] paramAnnotations = method.getParameterAnnotations()[i];
if(paramAnnotations.length <= 0) {
continue;
}
for(Annotation paramAnnotation : paramAnnotations){
if(RogerRequestParam.class.isAssignableFrom(paramAnnotation.getClass())) {
RogerRequestParam rogerRequestParam = (RogerRequestParam) paramAnnotation;
args[i++] = req.getParameter(rogerRequestParam.value());
}
}
}
}
2.使用策略模式实现(见源码)