DispatcherServlet本质上就是一个HttpServlet。同时它是SpringMVC中最为核心的一块——前端控制器。它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。
封装内容
web.xml
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>com.test.util.web.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
Controller.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
}
RequestMapping.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value();
}
ServletNotFoundException.java
public class ServletNotFoundException extends Exception {
private String message;
public ServletNotFoundException(String message) {
super(message);
}
}
DispatcherServlet.java
public class ServletManager extends HttpServlet {
// 存储请求和类的对应关系
private static Map<String, Class> classMap = new HashMap<>();
// 存储类和类对象的对应关系
private static Map<Class, Object> objectMap = new HashMap<>();
// 存储请求和方法的对应关系
private static Map<String, Method> methodMap = new HashMap<>();
/**
* 类加载器加载项目中多个Class文件的步骤:
* 1.获取类加载器
* 2.获取执行目录的根目录URL
* 3.通过根URL深度优先搜索找到所有.class的文件的URL
* 4.处理URL获取类全名
* 5.通过反射加载并该Class,执行相关操作
*/
static {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration en = classLoader.getResources("");
if (en.hasMoreElements()) {
URL rootURL = (URL) en.nextElement();
File rootFile = new File(rootURL.getPath());
analyzePath(rootFile, "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void analyzePath(File file, String path) {
if (file == null) {
return;
}
if (file.isDirectory()) {//目录处理
File[] files = file.listFiles();
for (File temp : files) {
analyzePath(temp, path + "." + temp.getName());
}
} else {//文件处理
// 处理 .com.donkfer.orm.Table.class
try {
//判断是否为.class文件
if (file.getName().endsWith(".class")) {
String classFullName = path.substring(1, path.lastIndexOf("."));
Class clazz = Class.forName(classFullName);
// 判断是不是api
if (clazz.getAnnotation(Controller.class) != null) {
loadClassAndMethods(clazz);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void loadClassAndMethods(Class clazz) throws IllegalAccessException, InstantiationException {
if (clazz != null) {
Object object = clazz.newInstance();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String requestMapping = method.getAnnotation(RequestMapping.class).value();
if (requestMapping != null) {
classMap.put(requestMapping, clazz);
methodMap.put(requestMapping, method);
if (objectMap.get(clazz) == null) {
objectMap.put(clazz, object);
}
}
}
}
}
public void executeMethod(HttpServletRequest request, HttpServletResponse response) {
try {
request.setCharacterEncoding("utf-8");
String path = request.getServletPath();
Method method = methodMap.get(path);
if (method != null) {
Class clazz = classMap.get(path);
Object object = objectMap.get(clazz);
method.invoke(object, request, response);
} else {
throw new ServletNotFoundException("Servlet is not found");
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
executeMethod(request, response);
}
}
封装结果
TestController.java
@Controller
public class TestController {
@RequestMapping("testOne.action")
public void testOne(HttpServletRequest request, HttpServletResponse response) {
System.out.println("testOne执行");
}
}