第一步:开发注解
package com.springmvc.annotation;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.omg.CORBA.portable.ValueBase;
@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface Controller {
String value() default "";
}
package com.springmvc.annotation;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target(FIELD)
public @interface Qualifier {
String value() default "";
}
package com.springmvc.annotation;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
public @interface RequestMapping {
String value() default "";
}
package com.springmvc.annotation;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface Service {
String value() default "";
}
第二步:测试类
Controller层
package com.xiaowei.controller;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.Qualifier;
import com.springmvc.annotation.RequestMapping;
import com.xiaowei.service.DataService;
@Controller
@RequestMapping("/demo")
public class DataController {
@Qualifier("dataService")
private DataService dataService;
@RequestMapping("insert")
public void insert(Integer id) {
dataService.insert(id);
}
@RequestMapping("query")
public void query(Integer id) {
dataService.query(id);
}
@RequestMapping("delete")
public void delete(Integer id) {
dataService.delete(id);
}
Service层
package com.xiaowei.serviceImpl;
import com.springmvc.annotation.Service;
import com.xiaowei.service.DataService;
@Service("dataService")
public class DataServiceImpl implements DataService {
@Override
public void insert(Integer id) {
System.out.println("this is insert");
}
@Override
public void query(Integer id) {
System.out.println("this is query");
}
@Override
public void delete(Integer id) {
System.out.println("this is delete");
}
@Override
public void update(Integer id) {
System.out.println("this is update");
}
}
第三步:创建DispatcherServlet(中央控制器)
package com.springmvc.servlet;
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.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletConfig;
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 com.springmvc.annotation.Controller;
import com.springmvc.annotation.Qualifier;
import com.springmvc.annotation.RequestMapping;
import com.springmvc.annotation.Service;
/**
* Servlet implementation class DispatcherServlet
*/
@WebServlet("/DispatcherServlet")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final List<String> componentClass = new ArrayList<String>();
private static final Map<String, Object> instanceMap = new ConcurrentHashMap<String, Object>();
private static final Map<String, Object> handleMap = new ConcurrentHashMap<String, Object>();
/**
* Default constructor.
*/
public DispatcherServlet() {
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
try {
// 1.扫描包,读取配置文件
componentScan("com.xiaowei");
// 2.IOC
createBean();
// 3.依赖注入
propertyInjection();
// 4.地址映射
handleMap();
} catch (Exception e) {
e.printStackTrace();
}
}
private void handleMap() {
if (instanceMap.size() <= 0) {
return;
}
for (Entry<String, Object> entry : instanceMap.entrySet()) {
// 如果是controller则建立映射关系
if (entry.getValue().getClass().isAnnotationPresent(Controller.class)) {
String basePath="";
//判断是否存在根路径
if(entry.getValue().getClass().isAnnotationPresent(RequestMapping.class)){
RequestMapping baseRm = entry.getValue().getClass().getAnnotation(RequestMapping.class);
basePath = baseRm.value();
}
Method[] methods = entry.getValue().getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping rm = method.getAnnotation(RequestMapping.class);
String path = rm.value();
//建立映射
handleMap.put(basePath+"/"+path,method);
}
}
}
}
}
/**
* 依赖注入
*/
private void propertyInjection() {
if (instanceMap.size() <= 0) {
return;
}
for (Entry<String, Object> entry : instanceMap.entrySet()) {
//获取实例化对对象的类声明属性
Field[] fields = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(Qualifier.class)) {
Qualifier qf = field.getAnnotation(Qualifier.class);
String key = qf.value();
//获取依赖实例对象
Object instance = instanceMap.get(key);
if (instance != null) {
try {
//依赖注入
field.set(entry.getValue(), instance);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 创建实例对象
*
* @throws ClassNotFoundException
*/
private void createBean() throws Exception {
if (componentClass.size() <= 0) {
return;
}
for (String className : componentClass) {
//取得所有类的class对象
Class<?> clazz = Class.forName(className.replace(".class", ""));
//判断注解实例化
if (clazz.isAnnotationPresent(Controller.class)) {
Object instance = clazz.newInstance();
Controller an = clazz.getAnnotation(Controller.class);
String key = an.value();
if (key.equals("")) {
key = clazz.getSimpleName();
}
//存放到instanceMap
instanceMap.put(key, instance);
} else if (clazz.isAnnotationPresent(Service.class)) {
Object instance = clazz.newInstance();
Service an = clazz.getAnnotation(Service.class);
String key = an.value();
if (key.equals("")) {
key = clazz.getSimpleName();
}
instanceMap.put(key, instance);
} else {
continue;
}
}
}
/**
* 组件扫描
*/
private void componentScan(String basePackeageName) {
// 获得基包的URl路径
URL url = this.getClass().getClassLoader().getResource("/" + basePackeageName.replaceAll("\\.", "/"));
// 获得基包的文件路径
String baseFilePath = url.getFile();
File baseFile = new File(baseFilePath);
if (baseFile.exists()) {
// 获得基包下所有的文件路径
String[] files = baseFile.list();
for (String filePath : files) {
File file = new File(baseFilePath + filePath);
//如果是类文件保存起来,是文件夹递归获取
if (file.isDirectory()) {
componentScan(basePackeageName + "." + file.getName());
} else {
System.out.println(basePackeageName + "." + file.getName());
componentClass.add(basePackeageName + "." + file.getName());
}
}
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取请求路径
String uri = request.getRequestURI();
String contextPath = request.getContextPath();
uri.replace(contextPath, "");
Method method = (Method)handleMap.get(uri);
if(method!=null){
Controller controller = method.getDeclaringClass().getAnnotation(Controller.class);
String clazzName = controller.value();
if(clazzName.equals("")){
clazzName = method.getDeclaringClass().getSimpleName();
}
Object obj = instanceMap.get(clazzName);
try {
//传参时,想到的方法就是动态代理
method.invoke(obj, 1);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
第四步:配置xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>myspringmvc</servlet-name>
<servlet-class>com.springmvc.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myspringmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>