在Spring中,只需要加上注解就可以自动寻找到匹配的方法,不需要web.xml配置路径,这虽然不算是web服务器的功能,但是还是进行了简单的原理模拟
我们现在不需要servlet,只需要写出Controller类,然后给类加上路径注解即可
WebServer,ServerHandler,HTTPResponse均不变
删除ServletMapping,ServletMappingConfig,Servlet ,HelloServlet 类
注解类,value就是路径,路径必须是“/test”这种结构的
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE })
public @interface RequestMapping {
String value() default "";
}
测试的Controller层
@RequestMapping(value = "/hello")
public class HelloController {
@RequestMapping(value = "/say")
public String sayHello() {
return "hello";
}
@RequestMapping(value = "/error")
public String error() {
return "error 404";
}
}
注解配置类,扫描包下所有的类,查看是否有注解,如果使用了注解就添加进list中
这里只是做了一个模拟,所以只扫描了当前文件夹下
public class MappingConfig {
// 扫描当前包下的所有的注解类
public static List<Class> searchClass() throws ClassNotFoundException {
File file = new File("./target/classes/com/example/fall/WebServer");
File[] files = file.listFiles();
List<Class> list = new ArrayList<>();
if(files != null) {
for (File i : files) {
String className = ("com.example.fall.WebServer." + i.getName());
className = className.substring(0, className.length() - 6);
Class clazz = Class.forName(className);
Annotation annotation = clazz.getAnnotation(RequestMapping.class);
if (annotation != null) {
list.add(clazz);
}
}
}
return list;
}
}
Dispatcher 类,加载的时候先获得被注解的类列表,然后每次都中列表中匹配路径
public class Dispatcher {
private static List<Class> classes;
static {
try {
classes = MappingConfig.searchClass();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void dispatcher(HttpRequest httpRequest, HTTPResponse httpResponse) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
String uri = httpRequest.getUri();
String clazzUri = "";
String methodUri = "";
int index1 = uri.indexOf("/");
int index2 = uri.indexOf("/", index1 + 1);
if (index2 != -1) {
clazzUri = uri.substring(0, index2);
int index3 = uri.indexOf("?", index2);
if (index3 != -1) {
methodUri = uri.substring(index2, index3);
} else {
methodUri = uri.substring(index2);
}
} else {
clazzUri = "/hello";
methodUri = "/error";
}
Object result = "Error 404";
for (Class i : classes) {
RequestMapping clazzAnno = (RequestMapping) i.getAnnotation(RequestMapping.class);
if (clazzAnno.value().equals(clazzUri)) {
Method[] methods = i.getDeclaredMethods();
for (Method j : methods) {
RequestMapping methodAnno = (RequestMapping) j.getAnnotation(RequestMapping.class);
if (methodAnno.value().equals(methodUri)) {
Object obj = i.newInstance();
result = j.invoke(obj);
}
}
}
}
httpResponse.write((String) result);
}
}
结果
访问http://localhost:8888/hello/say
出现hello
访问http://localhost:8888/hello/error
error 404