@AutoWired
package cn.luckybin.annaotation;
import java.lang.annotation.*;
/**
* 自动注入
*/
@Target({ElementType.FIELD})//修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时能获取
@Documented//生成文档
public @interface EnjoyAutowired {
String value() default "";
}
@Controller
package cn.luckybin.annaotation;
import java.lang.annotation.*;
/**
* 控制层
*/
@Target({ElementType.TYPE})//修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时能获取
@Documented//生成文档
public @interface EnjoyController {
String value() default "";
}
@Service
package cn.luckybin.annaotation;
import java.lang.annotation.*;
/**
* 业务层
*/
@Target({ElementType.TYPE})//修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时能获取
@Documented//生成文档
public @interface EnjoyService {
String value() default "";
}
@RequestMapping
package cn.luckybin.annaotation;
import java.lang.annotation.*;
/**
* URI
*/
@Target({ElementType.TYPE, ElementType.METHOD})//修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时能获取
@Documented//生成文档
public @interface EnjoyRequestMapping {
String value() default "";
}
@RequestParam
package cn.luckybin.annaotation;
import java.lang.annotation.*;
/**
* 请求参数
*/
@Target({ElementType.PARAMETER})//修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时能获取
@Documented//生成文档
public @interface EnjoyRequestParam {
String value() default "";
}
LybService.java
package cn.luckybin.service;
public interface LybService {
String query(String name, String tag);
}
LybServiceImpl.java
package cn.luckybin.service.impl;
import cn.luckybin.annaotation.EnjoyService;
import cn.luckybin.service.LybService;
@EnjoyService(value = "LybServiceImpl")
public class LybServiceImpl implements LybService {
//模拟返回参数
public String query(String name, String tag) {
return "name=" + name + ",tag=" + tag;
}
}
LybController.java
package cn.luckybin.controller;
import cn.luckybin.annaotation.*;
import cn.luckybin.service.LybService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 控制层
*/
@EnjoyController(value = "LybController")
@EnjoyRequestMapping(value = "/lyb")
public class LybController {
//注入实现类实例
@EnjoyAutowired(value = "LybServiceImpl")
private LybService lybService;
//设置路由参数
@EnjoyRequestMapping(value = "/query")
public void query(HttpServletRequest request, HttpServletResponse response, @EnjoyRequestParam("name") String name, @EnjoyRequestParam("tag") String tag) {
try {
//获取响应输出
PrintWriter printWriter = response.getWriter();
//调用业务层,获取结果
String result = lybService.query(name, tag);
//将结果返回给客户端
printWriter.write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package cn.luckybin.servlet;
import cn.luckybin.annaotation.*;
import cn.luckybin.controller.LybController;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 拦截所有Servlet
*/
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//存放类名: cn.luckybin.xxx.xxx.class
List classNames = new ArrayList();
//以URI作为Key,Controller作为实例对象,存储在map中
Map beans = new HashMap();
//以URI为Key,Method作为实例对象,存储在map中
Map handlerMap = new HashMap();
//初始化方法,最先执行
@Override
public void init(ServletConfig servletConfig) {
System.out.println("init");
//把所有的Bean扫描---扫描所有的class文件
scanPackage("cn.luckybin");//可以写到properties
//此时已经将我们项目中所有的.class文件的路径都在classNames集合中
System.out.println(classNames);
//将classNames中存储的path路径,去掉.class后缀,使用class.forName()方法将对象加载到容器中
doInstance();
//此时已经将所有加了@EnjoyController,@Service的类实例存入容器中
System.out.println(beans);
//根据bean进行依赖注入,被@EnjoyAutowired修饰的属性会被注入对应的依赖
doIoc();
/**
* 经过上面步骤,已经将我们的依赖都注入了
* 接下来就是将URI与我们Controller类中的方法建立映射关系
* lyb/query ---> method 建立URI与Method的映射关系
*/
buildUrlMapping();
}
//递归扫描,搭建.class文件
private void scanPackage(String basePackage) {
URL url = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));
String fileStr = url.getFile();
File file = new File(fileStr);
//找出所有的文件夹/文件
String[] filesStr = file.list();
for (String path : filesStr) {
File filePath = new File(fileStr + path);//
if (filePath.isDirectory()) {
//递归
scanPackage(basePackage + "." + path);//cn.luckybin....
} else {
//加入classNames
classNames.add(basePackage + "." + filePath.getName());//cn.luckybin....class
}
}
}
/**
* 将classNames中存储的path路径,去掉.class后缀,使用class.forName()方法将对象加载到容器中
* 以URI为key,Controller类作为Value
*/
private void doInstance() {
if (classNames.size() <= 0) {
System.out.println("包扫描失败.....");
return;
}
//遍历list中所有的class类,对这些类进行实例化
for (String className : classNames) {
//将所有的'.class'后缀替换成空字符串
String cn = className.replace(".class", "");
try {
//获取class对象
Class> clazz = Class.forName(cn);//cn.luckybin.xxxcontroller
//找出所有Controller类
if (clazz.isAnnotationPresent(EnjoyController.class)) {
Object instance = clazz.newInstance();//创建控制类
//获取Controller类中的URI
EnjoyRequestMapping requestMapping = clazz.getAnnotation(EnjoyRequestMapping.class);
String rmvalue = requestMapping.value();// '/lyb'
//以URI作为Key,Controller作为实例对象,存储在map中
beans.put(rmvalue, instance);
//找出所有Service
} else if (clazz.isAnnotationPresent(EnjoyService.class)) {
EnjoyService service = clazz.getAnnotation(EnjoyService.class);
Object instance = clazz.newInstance();
beans.put(service.value(), instance);
} else {
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
//把service注入到controller
public void doIoc() {
if (beans.entrySet().size() <= 0) {
System.out.println("没有一个实例化类");
}
//把map里所有的实例遍历出来
for (Map.Entry entry : beans.entrySet()) {
Object instance = entry.getValue();
//获取实例
Class> clazz = instance.getClass();
//找出Controller类
if (clazz.isAnnotationPresent(EnjoyController.class)) {
//获取所有属性
Field[] fields = clazz.getDeclaredFields();
System.out.println("fields=" + fields.length);
for (Field field : fields) {
//判断属性是否需要注入
if (field.isAnnotationPresent(EnjoyAutowired.class)) {
EnjoyAutowired autowired = field.getAnnotation(EnjoyAutowired.class);
//获取key
String key = autowired.value();
// if (key == null || "".equals(key)) {
// //如果没有写key,则将属性名作为key
// key = field.getName();
// }
//因为它是private,需要先将权限打开,否则无法注入
field.setAccessible(true);
try {
//注入实例
field.set(instance, beans.get(key));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
continue;
}
}
} else {
continue;
}
}
}
private void buildUrlMapping() {
if (beans.entrySet().size() <= 0) {
System.out.println("没有类的实例化.....");
return;
}
for (Map.Entry entry : beans.entrySet()) {
Object instance = entry.getValue();
Class> clazz = instance.getClass();
if (clazz.isAnnotationPresent(EnjoyController.class)) {
EnjoyRequestMapping requestMapping = clazz.getAnnotation(EnjoyRequestMapping.class);
String classUri = requestMapping.value(); // '/lyb'
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(EnjoyRequestMapping.class)) {
EnjoyRequestMapping methodMapping = method.getAnnotation(EnjoyRequestMapping.class);
String methodUri = methodMapping.value();
handlerMap.put(classUri + methodUri, method); // '/lyb/query'
} else {
continue;
}
}
} else {
continue;
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求路径 '/lyb/query' ->
String uri = req.getRequestURI();
String context = req.getContextPath();
String path = uri.replace(context, "");
Method method = (Method) handlerMap.get(path);
//根据key = /lyb到map去拿
LybController instance = (LybController) beans.get("/" + path.split("/")[1]);
//获取参数
Object arg[] = hand(req, resp, method);
try {
//调用该方法的实例及对应参数
method.invoke(instance, arg);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 根据目标方法含有的参数,从request中取出method中需要的参数
*
* @param request 请求对象
* @param response 响应对象
* @param method 目标方法
* @return
*/
private static Object[] hand(HttpServletRequest request, HttpServletResponse response, Method method) {
//拿到当前执行的方法有哪些参数
Class>[] paramClazzs = method.getParameterTypes();
//根据参数的个数,new 一个参数的数组,将方法里的所有参数赋值到args来
Object[] args = new Object[paramClazzs.length];
int args_i = 0;
int index = 0;
for (Class> paramClazz : paramClazzs) {
//判断是否为ServletRequest的子类
if (ServletRequest.class.isAssignableFrom(paramClazz)) {
args[args_i++] = request;
}
if (ServletResponse.class.isAssignableFrom(paramClazz)) {
args[args_i++] = response;
}
//获取该方法中所有带有注解的参数
Annotation[] paramAns = method.getParameterAnnotations()[index];
if (paramAns.length > 0) {
for (Annotation paramAn : paramAns) {
//判断是否为param注解
if (EnjoyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
EnjoyRequestParam rp = (EnjoyRequestParam) paramAn;
//从request对象中找到注解里的参数
args[args_i++] = request.getParameter(rp.value());
}
}
}
index++;
}
return args;
}
}
lyb
dispatcherServlet
cn.luckybin.servlet.DispatcherServlet
0
dispatcherServlet
/
码云
代码若有不足之处还望指出,虚心接受各位大佬指点!