本项目已开源,欢迎各位大佬访问并指正:仿写SpringMVC中的注解和方法映射功能
文章目录
- 一、仿写流程
- 1、初始化
- 2、测试
- 二、代码实现
- 1、自定义注解Controller和RequestMapping
- 2、扫描本项目下Controller下所有的java文件
- 3、识别注解,完成映射
- 4、编写Controller,准备测试
- 5、初始化并编写main方法,开始测试
- 6、执行,测试结果
一、仿写流程
1、初始化
- 通过扫描某路径下的文件夹和文件 通过字符串处理得到全限定名
- 传入指定包的地址
- 输出 List 里边的所有java文件(”.java")
- 反射创建对象
- url->对象 Map<String,Object>
- 识别是否有我们所需的注解,并获取注解内的值
- 识别类上的注解Controller
- 识别类上的注解RequestMapping,并获取value值
- 识别该类中方法上的注解RequestMapping,并获取value值
- 需要构建 每个类每个方法对应url的映射结构
2、测试
- 编写自定义注解和测试类
- 编写测试main方法,传入请求访问路径和方法,执行
二、代码实现
1、自定义注解Controller和RequestMapping
有关知识请直接点我借一步说话
- Controller
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
//类型+名称+默认值
String value() default "user";
}
- RequestMapping
@Target(value ={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value() default "index";
}
2、扫描本项目下Controller下所有的java文件
有关知识请移步
public class GetAllFiles {
static int count = 0;
public static List<String> getAllFiles(String path) {
System.out.println(path);
List<String> qualifiedPaths = new ArrayList<String>();
String fileType = ".java";// 指定文件类型
File file = new File(path);
long start = System.currentTimeMillis();
listAllFiles(file, fileType, qualifiedPaths);
long end = System.currentTimeMillis();
System.out.println("共花费:" + (end - start) + "毫秒");
System.out.println("有" + count + "个文件");
return qualifiedPaths;
}
public static void listAllFiles(File file, String fileType, List<String> qualifiedPaths){
if (file.isFile()){
count++;
System.out.println(file);
String path = file.getPath().replace('\\', '.');
int begin = path.indexOf("Controller");
int end = path.indexOf(".java");
String qualifiedPath = path.substring(begin, end);
qualifiedPaths.add(qualifiedPath);
System.out.println(qualifiedPath);
} else {
if (file.exists() && file.isDirectory()){
File[] files = file.listFiles();
for (File file1 : files){
listAllFiles(file1, fileType,qualifiedPaths);
}
}
}
}
}
3、识别注解,完成映射
public class SpringMVC {
//设置mapobj,key:拥有Controller注解的类的RequestMapping值,value:拥有Controller注解的类的class类实例
//记录注解value值和Controller类的class实例的映射
private static Map<String, Object> mapobj = new HashMap<String, Object>();
//设置map,key:Controller类的RequestMapping的vaule值,
//value:记录RequestMapping的value值和对应方法的映射
private static Map<String, HashMap<String, Method>> map = new HashMap<>();
//模拟服务器中DispatherServlet对前端传来的请求路径进行转发给各个Controller
public static void exec(String classPath,String methodPath){
if(mapobj.get(classPath)==null){
System.out.println("没有这个类 404");
}else {
if(map.get(classPath).get(methodPath)==null){
System.out.println("没有这个方法 404");
}else {
try {
map.get(classPath).get(methodPath).invoke(mapobj.get(classPath));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
public static void springmvc(String path) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
path = "D:\\appdata\\ssm-workspace\\Spring\\src\\Controller";
List<String> classNames = GetAllFiles.getAllFiles(path);
for (String className:classNames) {
Class cl = Class.forName(className);
//System.out.println(cl.getName());
//观察该类的所有注解,没鸟用,纯闲的
Annotation[] annotations = cl.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//判断java文件是否是Controller
Controller controller = (Controller) cl.getAnnotation(Controller.class);
if (controller!=null) {
//如果是Controller,找到注解在该类上的RequestMapping中的value值,将映射加入到mapobj,将value值加入到map的key中
RequestMapping mapping = (RequestMapping) cl.getAnnotation(RequestMapping.class);
mapobj.put(mapping.value(), cl.newInstance());
map.put(mapping.value(), new HashMap<String, Method>());
//遍历其中的所有方法,将每一个方法上的RequestMapping注解的value值和该方法完成映射绑定
Method[] methods = cl.getDeclaredMethods();
for (Method m:methods) {
Annotation[] annotations_m = m.getAnnotations();
for (Annotation annotation : annotations_m) {
RequestMapping requestMapping = (RequestMapping) m.getAnnotation(RequestMapping.class);
map.get(mapping.value()).put(requestMapping.value(), m);
}
}
}
}
//System.out.println(map.size());
System.out.println("映射结果:");
//1. 使用keySet方法遍历key,再通过key获取value
for(String key:map.keySet()){
System.out.println(key+" "+map.get(key));
}
}
}
4、编写Controller,准备测试
- TestController类
@Controller
@RequestMapping("test")
public class TestController {
@RequestMapping
public String index(){
System.out.println("test->index");
return "";
}
@RequestMapping("index1")
public String index1(){
System.out.println("test->index1");
return "";
}
}
- TestController2类
@Controller
@RequestMapping("test2")
public class TestController2 {
@RequestMapping("index2")
public void index2() {
System.out.println("test2->index2");
}
}
5、初始化并编写main方法,开始测试
public class Main {
static {
String path = Main.class.getResource("").getPath();
String packageName = Main.class.getPackage().getName();
String scannerPath = path.replaceAll(packageName, "Controller");
try {
SpringMVC.springmvc(scannerPath);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("测试结果:");
SpringMVC.exec("test", "index");
SpringMVC.exec("test", "index1");
SpringMVC.exec("test2", "index2");
}
}
6、执行,测试结果
可以看到完整的映射结果,几个样例的执行也没有问题,扣一波牛波一!!!