最近从网上看到一篇做迷你SpringMVC的文章,就决定跟着做一下研究一下
下面是具体的代码和解析
一、项目架构
这里我们缩减了注解的量只是用了最基本的几个注解来完成基本的映射调用
同时这里没有模拟持久层的操作,只是完成前端页面到服务层的映射调用
原文使用了Qualifier按名称进行注入,而我习惯使用@Autowired,所以进行了一部分修改
原文链接https://blog.csdn.net/m0_46995061/article/details/106836614
二、注解代码
1.Autowired
根据类型自动装配
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
public boolean required() default true;
}
2.Controller
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
public String value();
}
3.Service
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
public String value();
}
4.Repository
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {
public String value();
}
5.RequestMapping
保存映射路径
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
public String value();
}
三、DispatcherServelt
该类是SpringMVC的核心,它完成对所有请求的拦截并根据具体的路径去调用对应的方法进行请求的处理
//注解配置Servlet,需要使用servletapi3.0
//拦截所有请求
//设置启动时加载
//将包扫描的路径引入
@WebServlet(name = "dispatcherServlet",urlPatterns = "/*",loadOnStartup = 1,
initParams = {@WebInitParam(name = "base-package",value = "com.spring.springmvc")})
public class DispatcherServlet extends HttpServlet {
//扫描的基包
private String basepackage = "";
//基包下所有的全限定类名
private List<String> packageNames = new ArrayList<String>();
//注解实例化
private Map<String,Object> instanceMap = new HashMap<>();
//注解名称
private Map<String,String> nameMap = new HashMap<>();
//url和方法的映射关系
private Map<String, Method> urlMathodMap = new HashMap<>();
//Method和全限定类名的映射关系,通过Method找到该方法的对象利用反射执行
private Map<Method,String> methodPackageMap = new HashMap<>();
//重写了Servlet初始化方法,完成一整套容器初始化的执行流程
//这里使用了一点模板模式的概念,只是没有做类的解耦分离
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
basepackage = config.getInitParameter("base-package");
try {
//扫描包下的类
scanBasePackage(basepackage);
//实例化所有符合条件的类(注解了几个自定义注解的类)
instance(packageNames);
//依赖注入
executeIOC();
//生成映射
handlerUrlMethodMap();
}catch (Exception ex){
}
}
private void scanBasePackage(String basepackage){
// System.out.println(basepackage);
URL url = this.getClass().getClassLoader().getResource(basepackage.replaceAll("\\.","/"));
File basePackageFile = new File(url.getPath());
System.out.println("scan:"+basePackageFile);
File[] childFiles = basePackageFile.listFiles();
for(File file:childFiles){
if(file.isDirectory()){
scanBasePackage(basepackage+"."+file.getName());
}else if(file.isFile()){
packageNames.add(basepackage+"."+file.getName().split("\\.")[0]);
System.out.println(basepackage+"."+file.getName().split("\\.")[0]);
}
}
}
public void instance(List<String> packageNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if(packageNames.size()<1){
return;
}
for(String string:packageNames){
Class c = Class.forName(string);
if(c.isAnnotationPresent(Controller.class)){
Controller controller = (Controller)c.getAnnotation(Controller.class);
String controllerName = controller.value();
nameMap.put(string,controllerName);
instanceMap.put(controllerName,c.newInstance());
System.out.println("Controller : "+ string + ", value : "+controller.value());
}else if(c.isAnnotationPresent(Service.class)){
Service service = (Service) c.getAnnotation(Service.class);
String serviceName = service.value();
nameMap.put(string,serviceName);
instanceMap.put(serviceName,c.newInstance());
System.out.println("Service : "+ string + ", value : "+service.value());
}else if(c.isAnnotationPresent(Repository.class)){
Repository repository = (Repository) c.getAnnotation(Repository.class);
String repositoryName = repository.value();
nameMap.put(string,repositoryName);
instanceMap.put(repositoryName,c.newInstance());
System.out.println("Repository : "+ string + ", value : "+repository.value());
}
}
}
public void executeIOC() throws ClassNotFoundException, IllegalAccessException {
for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
Field[] fields = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
boolean isRequired = field.getAnnotation(Autowired.class).required();
field.setAccessible(true);
for(String name:instanceMap.keySet()){
Object object = instanceMap.get(name);
if(field.getType().isAssignableFrom(object.getClass())){
field.set(entry.getValue(),object);
}
}
}
}
}
}
public void handlerUrlMethodMap() throws ClassNotFoundException {
if(packageNames.size()<1){
return;
}
for(String name:packageNames){
Class c = Class.forName(name);
if(c.isAnnotationPresent(Controller.class)){
Method[] methods = c.getMethods();
StringBuffer stringBuffer = new StringBuffer();
if(c.isAnnotationPresent(RequestMapping.class)){
RequestMapping requestMapping = (RequestMapping) c.getAnnotation(RequestMapping.class);
stringBuffer.append(requestMapping.value());
}
for (Method method:methods){
//System.out.println("==================");
if(method.isAnnotationPresent(RequestMapping.class)){
RequestMapping requestMapping = (RequestMapping)method.getAnnotation(RequestMapping.class);
stringBuffer.append(requestMapping.value());
urlMathodMap.put(stringBuffer.toString(),method);
System.out.println(stringBuffer);
methodPackageMap.put(method,name);
}
}
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
String uri = req.getRequestURI();
String contextPath = req.getContextPath();
String path = uri.replaceAll(contextPath,"");
Method method = urlMathodMap.get(path);
if(method==null){
Writer writer = resp.getWriter();
writer.write("网站输入无效404");
}else{
String packageName = methodPackageMap.get(method);
String controllerName =nameMap.get(packageName);
System.out.println(controllerName);
System.out.println(instanceMap);
MyController myController = (MyController) instanceMap.get(controllerName);
try{
System.out.println(method.getName());
method.setAccessible(true);
method.invoke(myController);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
四、Controller层代码
@Controller("myController")
public class MyController {
@Autowired
MyService service;
@RequestMapping("/aaa")
public String first(){
System.out.println("It's controller");
service.invokeService();
return "";
}
}
五、Service层代码
public interface MyService {
public void invokeService();
}
@Service("myService")
public class MyServiceImpl implements MyService {
@Override
public void invokeService() {
System.out.println("I'ts Service");
}
}
六、maven依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>