手动实现spring中的@RequestMapping注解

初期介绍

@RequestMapping注解的使用

用过Spring框架的同学或许都使用过@RequestMapping注解吧,这个注解可以方便的将URL映射到我们的方法中。那么,这个是如何实现的呢?在之前我有一篇博客,关于手动实现@ModelAttribute注解的文章;在这篇文章中,采用了java的注解以及反射技术实现了web表单提交的{name:value}值注入到指定的对象中去。同样,我们也可以使用相同的技术{注解、反射}来实现@RequestMapping注解的功能。

@RequestMapping注解功能的一些原理

要想实现@RequestMapping注解,首先需要解决的就是 url 地址与方法的捆绑问题。这个时候可以考虑使用 Java 语言自带的 Map 这个数据结构,key 为 String 类型的 url 地址,value 为 Method 类型的对象,因此就可以实现 url 地址与方法的绑定。

开始实现

Mapping.java

首先我们需要创建一个注解,这个注解作用在METHOD上,生命周期是在运行时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package test;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Mapping {
String value();
}

Main.java

有了上面的注解,我们就可以方便的实现@RequestMapping这个注解了;首先在整个类创建时先初始化一个 Map 对象进行存储 url 与 Method 对象;然后写一个初始化函数 init(), 在这个函数中实现对被注解作用的方法进行与注解 value 值的绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import test.Mapping;

public class Main {

private static Map<String, Method> methodMap;

static {
methodMap = new HashMap<>();
}

@Mapping(value = "/name")
public void name(String name) {
System.out.println("my name is " + name);
}

@Mapping(value = "/sex")
public void sex(String sex) {
System.out.println("I am a " + sex);
}

public void init() {
Method[] methods = Main.class.getMethods();
for (Method each : methods) {
if (each.isAnnotationPresent(Mapping.class)) {
Mapping maped = each.getAnnotation(Mapping.class);
methodMap.put(maped.value(), each);
}
}
}

public void exec(Method method, Object o, String param) {
try {
method.invoke(o, param);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
Main m = new Main();
m.init();
m.exec(m.methodMap.get("/name"), m, args[0]);
m.exec(m.methodMap.get("/sex"), m, args[1]);
}

}