概述:
本示例实现了简单的IOC和依赖注入,实现了 Controller, Service, RequestMapping, Quatifier 等注解。
具体步骤:
- 在Servlet初始化时递归扫描对应路径下所用的class,存放到packageNames(List)中
- 遍历List,记录被Controller和Service注解修饰的class,创建其示例并和path做好映射,存放在instanceMap中。
- 遍历map中被Controller注解修饰的class,获取其内部被RequestMapping注解修饰的方法引用,并且和Controller注解的value + RequestMapping注解的value 做映射存放在handerMap中
- 遍历instanceMap中bean带有Quatifier 注解的field,读取该注解的value根据这个值并从instanceMap获取到对应的bean,将这个bean设置到对应的field上面
- 根据requestURI来获取到对应Controller和Method的引用,通过反射来调用这个方法
代码实现:
DispatcherServlet.java
package main.com.servlet;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
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;
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 main.com.annotation.Controller;
import main.com.annotation.Quatifier;
import main.com.annotation.RequestMapping;
import main.com.annotation.Service;
import main.com.controller.BaseController;
/**
* Created by wb-tianlihui on 2017/11/3.
*/
@WebServlet(name = "springmvc", urlPatterns = {"/*", "/helloworld"}, loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
List<String> packageNames = new ArrayList<String>();
// 所有类的实例,key是注解的value,value是所有类的实例
Map<String, Object> instanceMap = new HashMap<String, Object>();
Map<String, Object> handerMap = new HashMap<String, Object>();
/**
* 地柜扫描包下的所有文件
* @param Package
*/
private void scanPackageFiles(String Package) {
URL url = this.getClass().getClassLoader().getResource("/" + replaceTo(Package));
// 将所有的.转义获取对应的路径
String pathFile = url.getFile();
File file = new File(pathFile);
String fileList[] = file.list();
for (String path : fileList) {
File eachFile = new File(pathFile + path);
if (eachFile.isDirectory()) {
scanPackageFiles(Package + "." + eachFile.getName());
} else {
packageNames.add(Package + "." + eachFile.getName());
}
}
}
private String replaceTo(String path) {
return path.replaceAll("\\.", "/");
}
/**
* 将扫描包下所有带有@Controller和Service注解的类创建好示例和对应Controller里面的value映射起来
* @param
*/
private void filterAndInstance() throws Exception {
if (packageNames.size() <= 0) {
return;
}
for (String className : packageNames) {
Class<?> cName = Class.forName(className.replace(".class", "").trim());
if (cName.isAnnotationPresent(Controller.class)) {
Object instance = cName.newInstance();
Controller controller = cName.getAnnotation(Controller.class);
String key = controller.value();
instanceMap.put(key, instance);
} else if (cName.isAnnotationPresent(Service.class)) {
Object instance = cName.newInstance();
Service service = cName.getAnnotation(Service.class);
String key = service.value();
instanceMap.put(key, instance);
} else {
continue;
}
}
}
/**
* 将完整的path和Method做好映射
* @param
*/
private void handerPathAndMethodMap() {
if (instanceMap.size() <= 0) {return;}
for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
if (entry.getValue().getClass().isAnnotationPresent(Controller.class)) {
Controller controller = entry.getValue().getClass().getAnnotation(Controller.class);
String ctvalue = controller.value();
Method[] methods = entry.getValue().getClass().getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping rm = method.getAnnotation(RequestMapping.class);
String rmvalue = rm.value();
handerMap.put("/" + ctvalue + "/" + rmvalue, method);
} else {
continue;
}
}
} else {
continue;
}
}
}
/**
* 将bean中的依赖注入进去
* @param
*/
private void myIoc() {
if (instanceMap.isEmpty()){
return;
}
for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
// 拿到里面的所有属性
Field fields[] = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
// 可访问私有属性
field.setAccessible(true);
if (field.isAnnotationPresent(Quatifier.class)){
Quatifier quatifier = field.getAnnotation(Quatifier.class);
String value = quatifier.value();
field.setAccessible(true);
try {
field.set(entry.getValue(), instanceMap.get(value));
} catch (Exception e) {
e.printStackTrace();
}
}else{
continue;
}
}
}
}
@Override
public void init() throws ServletException {
super.init();
// 包扫描,获取包中的文件
scanPackageFiles("main.com");
try {
filterAndInstance();
handerPathAndMethodMap();
myIoc();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getRequestURI();
String context = req.getContextPath();
String path = url.replace(context, "");
Method method = (Method) handerMap.get(path);
BaseController controller = (BaseController) instanceMap.get(path.split("/")[1]);
try {
method.invoke(controller, new Object[] { req, resp});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
注解:
package main.com.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by wb-tianlihui on 2017/11/3.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Controller {
String value() default "";
}
package main.com.annotation;
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;
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Quatifier {
String value() default "";
}
package main.com.annotation;
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;
/**
* Created by wb-tianlihui on 2017/11/3.
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
String value() default "";
}
package main.com.annotation;
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;
/**
* Created by wb-tianlihui on 2017/11/3.
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
String value() default "";
}
Controller:
package main.com.controller;
/**
* Created by wb-tianlihui on 2017/11/5.
*/
public class BaseController {
}
package main.com.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import main.com.annotation.Controller;
import main.com.annotation.Quatifier;
import main.com.annotation.RequestMapping;
import main.com.service.MyService;
/**
*
* @author wb-tianlihui
* @date 2017/11/5
*/
@Controller("tianlh")
public class MyController extends BaseController {
@Quatifier("myService")
MyService myService;
@RequestMapping("insert")
public String insert(HttpServletRequest request, HttpServletResponse response) throws IOException {
myService.insert(null);
response.setContentType("text/html;charset=utf8");
response.getWriter().println("MyController被调用");
return "";
}
}
Service:
package main.com.service;
import java.util.Map;
/**
* Created by wb-tianlihui on 2017/11/5.
*/
public interface MyService {
int insert(Map map);
}
package main.com.service;
import java.util.Map;
import main.com.annotation.Service;
/**
* Created by wb-tianlihui on 2017/11/5.
*/
@Service("myService")
public class MyServiceImpl implements MyService {
@Override
public int insert(Map map) {
System.out.println("MyService被调用");
return 0;
}
}
目录结构:
运行结果:
控制台打印:MyService被调用