@GPAutowired注解如下:
package com.tom.mvcframework.annotation;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPAutowired {
String value() default “”;
}
@GPController注解如下:
package com.tom.mvcframework.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPController {
String value() default “”;
}
@GPRequestMapping注解如下:
package com.tom.mvcframework.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPRequestMapping {
String value() default “”;
}
@GPRequestParam注解如下:
package com.tom.mvcframework.annotation;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GPRequestParam {
String value() default “”;
}
1.4 配置注解
配置业务实现类DemoService:
package com.tom.demo.service.impl;
import com.tom.demo.service.IDemoService;
import com.tom.mvcframework.annotation.GPService;
/**
- 核心业务逻辑
*/
@GPService
public class DemoService implements IDemoService{
public String get(String name) {
return "My name is " + name;
}
}
配置请求入口类DemoAction:
package com.tom.demo.mvc.action;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tom.demo.service.IDemoService;
import com.tom.mvcframework.annotation.GPAutowired;
import com.tom.mvcframework.annotation.GPController;
import com.tom.mvcframework.annotation.GPRequestMapping;
import com.tom.mvcframework.annotation.GPRequestParam;
@GPController
@GPRequestMapping(“/demo”)
public class DemoAction {
@GPAutowired private IDemoService demoService;
@GPRequestMapping(“/query”)
public void query(HttpServletRequest req, HttpServletResponse resp,
@GPRequestParam(“name”) String name){
String result = demoService.get(name);
try {
resp.getWriter().write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
@GPRequestMapping(“/add”)
public void add(HttpServletRequest req, HttpServletResponse resp,
@GPRequestParam(“a”) Integer a, @GPRequestParam(“b”) Integer b){
try {
resp.getWriter().write(a + “+” + b + “=” + (a + b));
} catch (IOException e) {
e.printStackTrace();
}
}
@GPRequestMapping(“/remove”)
public void remove(HttpServletRequest req,HttpServletResponse resp,
@GPRequestParam(“id”) Integer id){
}
}
至此,配置全部完成。
所有的核心逻辑全部写在init()方法中,代码如下:
package com.tom.mvcframework.v1.servlet;
import com.tom.mvcframework.annotation.GPAutowired;
import com.tom.mvcframework.annotation.GPController;
import com.tom.mvcframework.annotation.GPRequestMapping;
import com.tom.mvcframework.annotation.GPService;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
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.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
public class GPDispatcherServlet 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 {}
@Override
public void init(ServletConfig config) throws ServletException {
InputStream is = null;
try{
Properties configContext = new Properties();
is = this.getClass().getClassLoader().getResourceAsStream(config.getInitParameter (“contextConfigLocation”));
configContext.load(is);
String scanPackage = configContext.getProperty(“scanPackage”);
doScanner(scanPackage);
for (String className : mapping.keySet()) {
if(!className.contains(“.”)){continue;}
Class<?> clazz = Class.forName(className);
if(clazz.isAnnotationPresent(GPController.class)){
mapping.put(className,clazz.newInstance());
String baseUrl = “”;
if (clazz.isAnnotationPresent(GPRequestMapping.class)) {
GPRequestMapping requestMapping = clazz.getAnnotation (GPRequestMapping.class);
baseUrl = requestMapping.value();
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if(!method.isAnnotationPresent(GPRequestMapping.class)){ continue; }
GPRequestMapping requestMapping = method.getAnnotation (GPRequestMapping.class);
String url = (baseUrl + “/” + requestMapping.value()).replaceAll(“/+”, “/”);
mapping.put(url, method);
System.out.println("Mapped " + url + “,” + method);
}
}else if(clazz.isAnnotationPresent(GPService.class)){
GPService service = clazz.getAnnotation(GPService.class);
String beanName = service.value();
if(“”.equals(beanName)){beanName = clazz.getName();}
Object instance = clazz.newInstance();
mapping.put(beanName,instance);
for (Class<?> i : clazz.getInterfaces()) {
mapping.put(i.getName(),instance);
}
}else {continue;}
}
for (Object object : mapping.values()) {
if(object == null){continue;}
Class clazz = object.getClass();
if(clazz.isAnnotationPresent(GPController.class)){
Field [] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if(!field.isAnnotationPresent(GPAutowired.class)){continue; }
GPAutowired autowired = field.getAnnotation(GPAutowired.class);
String beanName = autowired.value();
if(“”.equals(beanName)){beanName = field.getType().getName();}
field.setAccessible(true);
try {
field.set(mapping.get(clazz.getName()),mapping.get(beanName));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
}finally {
if(is != null){
try {is.close();} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.print(“GP MVC Framework is init”);
}
private void doScanner(String scanPackage) {
URL url = this.getClass().getClassLoader().getResource(“/” + scanPackage.replaceAll (“\.”,“/”));
File classDir = new File(url.getFile());
for (File file : classDir.listFiles()) {
if(file.isDirectory()){ doScanner(scanPackage + “.” + file.getName());}else {
if(!file.getName().endsWith(“.class”)){continue;}
String clazzName = (scanPackage + “.” + file.getName().replace(“.class”,“”));
mapping.put(clazzName,null);
}
}
}
}
重点实现doGet()和doPost()方法,实际上就是在doGet()和doPost()方法中调用doDispatch()方法,具体代码如下:
public class GPDispatcherServlet 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 {
doDispatch(req,resp);
} catch (Exception e) {
resp.getWriter().write("500 Exception " + Arrays.toString(e.getStackTrace()));
}
}
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[]> params = req.getParameterMap();
method.invoke(this.mapping.get(method.getDeclaringClass().getName()),new Object[]{req,resp,params.get(“name”)[0]});
}
@Override
public void init(ServletConfig config) throws ServletException {
…
}
}
在1.0版本上进行优化,采用常用的设计模式(工厂模式、单例模式、委派模式、策略模式),将init()方法中的代码进行封装。按照之前的实现思路,先搭基础框架,再“填肉注血”,具体代码如下:
//初始化阶段
@Override
public void init(ServletConfig config) throws ServletException {
//1. 加载配置文件
doLoadConfig(config.getInitParameter(“contextConfigLocation”));
//2. 扫描相关的类
doScanner(contextConfig.getProperty(“scanPackage”));
//3. 初始化扫描到的类,并且将它们放入IoC容器中
doInstance();
//4. 完成依赖注入
doAutowired();
//5. 初始化HandlerMapping
initHandlerMapping();
System.out.println(“GP Spring framework is init.”);
}
声明全局成员变量,其中IoC容器就是注册时单例的具体案例:
//保存application.properties配置文件中的内容
private Properties contextConfig = new Properties();
//保存扫描的所有的类名
private List classNames = new ArrayList();
//传说中的IoC容器,我们来揭开它的神秘面纱
//为了简化程序,暂时不考虑ConcurrentHashMap
//主要还是关注设计思想和原理
private Map<String,Object> ioc = new HashMap<String,Object>();
//保存url和Method的对应关系
private Map<String,Method> handlerMapping = new HashMap<String,Method>();
实现doLoadConfig()方法:
//加载配置文件
private void doLoadConfig(String contextConfigLocation) {
//直接通过类路径找到Spring主配置文件所在的路径
//并且将其读取出来放到Properties对象中
//相当于将scanPackage=com.tom.demo保存到了内存中
InputStream fis = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(fis);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != fis){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
Java面试核心知识点笔记
其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。
Java中高级面试高频考点整理
最后分享Java进阶学习及面试必备的视频教学
直到现在。**
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-4oaRCFOc-1711182444003)]
[外链图片转存中…(img-Po8KU8NP-1711182444004)]
[外链图片转存中…(img-HLPcpwim-1711182444005)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-qdSfRPje-1711182444005)]
Java面试核心知识点笔记
其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。
[外链图片转存中…(img-FQBU3SRW-1711182444006)]
Java中高级面试高频考点整理
[外链图片转存中…(img-ZvcGib10-1711182444007)]
[外链图片转存中…(img-PiiYYZ4B-1711182444007)]
最后分享Java进阶学习及面试必备的视频教学
[外链图片转存中…(img-NLwnoVet-1711182444008)]