思路分析
- 在服务器启动时,就扫描包下所有类:得到有注解
的类@Controller
- 反射生成这个类的实例对象:
object
- 遍历类里所有的方法,得到方法对象:
method
- 获取每个方法上
配置的映射路径:@RequestMapping
mappingPath
- 把方法对象
和类实例对象method
,封装成对象:object
MvcMethod
- 以
为key,mappingPath
对象为value,保存到一个Map中MvcMethod
- 反射生成这个类的实例对象:
- 当客户端请求到
时DispatcherServlet
- 获取请求的资源路径:path
- 从Map容器中找到对应的
MvcMethod
- 反射执行
中的方法对象MvcMethod
实现
@Controller
注解
@Controller
package com.lily.SpringMVC_02;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) //运行在类上
@Retention(RetentionPolicy.RUNTIME) //存活到运行
public @interface Controller {
}
@RequestMapping
@RequestMapping
package com.lily.SpringMVC_02;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 功能描述:〈用在业务控制器的方法上,用来声明 方法的路径〉
*/
@Target(ElementType.METHOD) //元注解: 表示在方法总运行
@Retention(RetentionPolicy.RUNTIME) //元注解: 表示保留到运行阶段
public @interface RequestMapping {
String value(); //配置的映射路径
}
MvcMethod
MvcMethod
package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日21时13分
*/
import java.lang.reflect.Method;
public class MvcMethod {
private Method method;
private Object object;
public MvcMethod() {
}
public MvcMethod(Method method, Object object) {
this.method = method;
this.object = object;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
DispatcherServlet
DispatcherServlet
/**
package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日22时26分
*/
import com.lily.util.ClassScannerUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet(urlPatterns = "*.do", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
/**
* 功能描述:〈重写init方法,配置注解:loadOnStartup,当值是整数,代表服务器启动时执行init方法〉
*/
private Map<String, MvcMethod> map = new HashMap<>();
@Override
public void init() throws ServletException {
try {
List<Class<?>> classsFromPackage = ClassScannerUtils.getClasssFromPackage("com.lily.web");
for (Class<?> clazz : classsFromPackage) {
boolean isController = clazz.isAnnotationPresent(Controller.class);
if (!isController) {
System.out.println(clazz + "类没有Controller注解");
continue;
}
Object object = clazz.newInstance();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
boolean isRequestMapping = method.isAnnotationPresent(RequestMapping.class);
if (isRequestMapping) {
RequestMapping getRequestMapping = method.getAnnotation(RequestMapping.class);
String MappingPath = getRequestMapping.value();
MvcMethod mvcMethod = new MvcMethod(method, object);
map.put(MappingPath, mvcMethod);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String uri = request.getRequestURI();
String contextPath = request.getContextPath();
String substring = uri.substring(contextPath.length(), uri.lastIndexOf("."));
MvcMethod mvcMethod = map.get(substring);
try {
mvcMethod.getMethod().invoke(mvcMethod.getObject(), request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
ClassScannerUtils
package com.lily.util;
import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class ClassScannerUtils {
/**
* 获得包下面的所有的class
*
* @param
* @return List包含所有class的实例
*/
public static List<Class<?>> getClasssFromPackage(String packageName) {
List clazzs = new ArrayList<>();
// 是否循环搜索子包
boolean recursive = true;
// 包名对应的路径名称
String packageDirName = packageName.replace('.', '/');
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
findClassInPackageByFile(packageName, filePath, recursive, clazzs);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return clazzs;
}
/**
* 在package对应的路径下找到所有的class
*/
public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive,
List<Class<?>> clazzs) {
File dir = new File(filePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
// 在给定的目录下找到所有的文件,并且进行条件过滤
File[] dirFiles = dir.listFiles(new FileFilter() {
public boolean accept(File file) {
boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
boolean acceptClass = file.getName().endsWith("class");// 接受class文件
return acceptDir || acceptClass;
}
});
for (File file : dirFiles) {
if (file.isDirectory()) {
findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
} else {
String className = file.getName().substring(0, file.getName().length() - 6);
try {
clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}