第一版没有使用设计模式,没有封装框架,只是简单的实现了IOC容器跟,DispatcherServlet处理请求
基本注解
/**
* @author success
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
String value() default "";
}
---------------------------------------------
/**
* @author lxz
* @version 1.0
* @className Controller
* @description TODO
* @Date 2019/9/3 10:18
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
String value() default "";
}
---------------------------------------------
/**
* @author lxz
* @version 1.0
* @className RequestMapping
* @description TODO
* @Date 2019/9/3 10:18
**/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
String value() default "";
}
---------------------------------------------
/**
* @author lxz
* @version 1.0
* @className RequestParam
* @description TODO
* @Date 2019/9/3 10:18
**/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
String value() default "";
}
---------------------------------------------
/**
* @author lxz
* @version 1.0
* @className Service
* @description TODO
* @Date 2019/9/3 10:18
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
String value() default "";
}
测试代码
Action(controller)
/**
* @author lxz
* @version 1.0
* @className DemoAction
* @description TODO
* @Date 2019/9/3 10:42
**/
@Controller
@RequestMapping("/demo")
public class DemoAction {
@Autowired
private DemoService demoService;
@RequestMapping("/query")
public void query(HttpServletRequest req, HttpServletResponse res, @RequestParam("name") String name) {
String result = demoService.get(name);
try {
res.getWriter().write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
service
public interface DemoService {
public String get(String name);
}
---------------------------------------------
/**
* @author lxz
* @version 1.0
* @className DemoServiceImpl
* @description TODO
* @Date 2019/9/3 10:40
**/
@Service
public class DemoServiceImpl implements DemoService {
@Override
public String get(String name) {
return "my name is :" +name;
}
}
web.xml配置
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>gpmvc</servlet-name>
<servlet-class>com.apusic.mvcframework.v1.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gpmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
application.properties
scanPackage=com.apusic.demo
核心类DispatcherServlet,继承了HttpServlet,重写了init,doGet,doPost方法.
流程init()初始化时,会扫描注解,把bean添加到IOC容器
处理请求的时候调用核心方法doDispath()处理
/**
* @author lxz
* @version 1.0
* @className DispatcherServlet
* @description TODO
* @Date 2019/9/3 10:05
**/
public class DispatcherServlet extends HttpServlet {
private Map<String, Object> mapping = new HashMap<String, Object>();
@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 {
try {
this.doDispatch(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replace(contextPath, "").replaceAll("/+", "/");
if (!this.mapping.containsKey(url)) {
resp.getWriter().write("404 Not Found");
return;
}
Method method = (Method) this.mapping.get(url);
Map<String, String[]> parameterMap = req.getParameterMap();
String name = method.getDeclaringClass().getName();
method.invoke(this.mapping.get(method.getDeclaringClass().getName()), new Object[]{req, resp, parameterMap.get(
"name")[0]});
}
@Override
public void init() throws ServletException {
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("application.properties")) {
Properties ps = new Properties();
ps.load(is);
String scanPackage = ps.getProperty("scanPackage");
doScanner(scanPackage);
for (String className : mapping.keySet()) {
if (!className.contains(".")) {
continue;
}
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(Controller.class)) {
mapping.put(className, clazz.newInstance());
String baseUrl = "";
if (clazz.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
baseUrl = requestMapping.value();
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(RequestMapping.class)) {
continue;
}
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String url = baseUrl + requestMapping.value().replace("/+", "/");
mapping.put(url, method);
System.out.println("Mapped" + url + "," + method);
}
} else if (clazz.isAnnotationPresent(Service.class)) {
Service service = clazz.getAnnotation(Service.class);
String beanName = service.value();
if ("".equals(beanName)) {
beanName = clazz.getName();
}
Object instance = clazz.newInstance();
mapping.put(beanName, instance);
for (Class<?> anInterface : clazz.getInterfaces()) {
mapping.put(anInterface.getName(), instance);
}
} else {
continue;
}
}
for (Object object : mapping.values()) {
if (object == null) {
continue;
}
Class<?> clazz = object.getClass();
if (clazz.isAnnotationPresent(Controller.class)) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowired.class)) {
continue;
}
String beanName = field.getAnnotation(Autowired.class).value();
if ("".equals(beanName)) {
beanName = field.getType().getName();
field.setAccessible(true);
field.set(mapping.get(clazz.getName()), mapping.get(beanName));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("mvc framework is init");
}
}
private void doScanner(String scanPackage) {
URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
if (url != null) {
File file = new File(url.getFile());
for (File listFile : Objects.requireNonNull(file.listFiles())) {
if (listFile.isDirectory()) {
doScanner(scanPackage + "." + listFile.getName());
} else {
if (file.getName().endsWith(".class")) {
continue;
}
String className = (scanPackage + "." + listFile.getName().replace(".class", ""));
mapping.put(className, null);
}
}
}
}
}
此时spring核心原理已经写出来了.
后续更新优化版本