手写SpringBoot(一)之简易版SpringBoot

手写SpringBoot(一)之简易版SpringBoot

  1. 添加依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.axj</groupId><artifactId>spring-boot-base</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>my-spring-boot</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.18</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>9.0.60</version></dependency></dependencies></project>
    
  2. 启动Spring容器

  • 定义MySpringBootApplication标识注解,对应SpringBootApplication
package cn.axj.springboot.my.annnotation;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Documented
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
public @interface MySpringBootApplication {
}

Configuration 注解表明该注解标注的类是一个配置类,在AnnotationConfigApplication 里面会解析这个类,并加载相应的容器bean

CompontScan 注解定义Configuration配置类下的扫描路径,如果不传,默认扫描标注类的包名。所以SpringBoot默认会扫描Application类下的当前包以及子包路径。

  • 定义MySpringApplication类,对应SpringApplication
package cn.axj.springboot.my.boot;import cn.axj.springboot.my.web.container.WebContainer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;public class MySpringApplication {public static void run(Class<?> clazz,String[] args) {//启动Spring容器AnnotationConfigWebApplicationContext annotationConfigApplicationContext = new AnnotationConfigWebApplicationContext();annotationConfigApplicationContext.register(clazz);annotationConfigApplicationContext.refresh();//启动tomcat容器WebContainer.startContainer(annotationConfigApplicationContext);}
}

register(clazz)通过传入的class对象扫描步骤二中Configuration和ComponentScan定义的路径地址,扫描组件注入到容器中

  1. 启动tomcat

    启动tomcat

    配置DispatcherServlet

package cn.axj.springboot.my.web.container;import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;public abstract class WebContainer{public static void startContainer(WebApplicationContext webApplicationContext){System.out.println("启动Web容器");Tomcat tomcat = new Tomcat();Server server = tomcat.getServer();Service service = server.findService("Tomcat");Connector connector = new Connector();connector.setPort(8080);StandardEngine engine = new StandardEngine();engine.setDefaultHost("localhost");Host host = new StandardHost();host.setName("localhost");String contextPath = "";Context context = new StandardContext();context.setPath(contextPath);context.addLifecycleListener(new Tomcat.FixContextListener());host.addChild(context);engine.addChild(host);service.setContainer(engine);service.addConnector(connector);//配置dispatcherServlet,Springmvc专属tomcat.addServlet(contextPath,"dispatcher",new DispatcherServlet(webApplicationContext));context.addServletMappingDecoded("/*","dispatcher");try {tomcat.start();} catch (LifecycleException e) {throw new RuntimeException(e);}}
}

至此,一个简易版的SpringBoot就完成了。

整个结构如下图所示

在这里插入图片描述

下面进行测试,新建一个user-service模块

  1. 引入自己写的springboot依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.axj</groupId><artifactId>spring-boot-base</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>user-service</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>cn.axj</groupId><artifactId>my-spring-boot</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
</project>
  1. 在cn.axj.user下面创建UserApplication
package cn.axj.user;import cn.axj.springboot.my.annnotation.MySpringBootApplication;
import cn.axj.springboot.my.boot.MySpringApplication;@MySpringBootApplication
public class UserApplication {public static void main(String[] args) {MySpringApplication.run(UserApplication.class, args);}
}
  1. 新建controller层TestController
package cn.axj.user.controller;import cn.axj.user.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
public class TestController {@Resourceprivate UserService userService;@GetMapping("/test")public String test(){return userService.test();}
}
  1. 新建service层UserService
package cn.axj.user.service;import org.springframework.stereotype.Service;@Service
public class UserService {public String test(){return "hello";}
}
  1. 启动main方法
启动Web容器
三月 27, 2024 5:55:51 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8080"]
三月 27, 2024 5:55:51 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
三月 27, 2024 5:55:51 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.75]
三月 27, 2024 5:55:52 下午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
警告: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [322] milliseconds.
三月 27, 2024 5:55:52 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8080"]
三月 27, 2024 5:56:07 下午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring DispatcherServlet 'dispatcher'
三月 27, 2024 5:56:07 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
信息: Initializing Servlet 'dispatcher'
三月 27, 2024 5:56:08 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
信息: Completed initialization in 443 ms
三月 27, 2024 5:56:08 下午 org.springframework.web.servlet.DispatcherServlet noHandlerFound
警告: No mapping for GET /
三月 27, 2024 5:56:08 下午 org.springframework.web.servlet.DispatcherServlet noHandlerFound
警告: No mapping for GET /
三月 27, 2024 5:56:08 下午 org.springframework.web.servlet.DispatcherServlet noHandlerFound
警告: No mapping for GET /favicon.ico

至此项目启动完成

  1. 打开浏览器,访问localhost:8080/test,看到返回test字符串,代表成功

当我们想将tomcat换成netty或者是underTow容器怎么实现呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/573153.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——排序算法

1、排序的概念 排序是指的是将一组数据&#xff08;如数字、单词、记录等&#xff09;按照某种特定的顺序&#xff08;升序或降序&#xff09;进行排列的过程。排序算法是实现排序的程序或方法&#xff0c;它们在软件开发和数据处理中扮演着至关重要的角色。 排序算法可以根据…

强化基础-Java-泛型

什么是泛型&#xff1f; 泛型其实就参数化类型&#xff0c;也就是说这个类型类似一个变量是可变的。 为什么会有泛型&#xff1f; 在没有泛型之前&#xff0c;java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷&#xff1a; 1 获取值的时候必须进行强转 2 没有…

[BT]BUUCTF刷题第9天(3.27)

第9天&#xff08;共2题&#xff09; [护网杯 2018]easy_tornado 打开网站就是三个txt文件 /flag.txt flag in /fllllllllllllag/welcome.txt render/hints.txt md5(cookie_secretmd5(filename))当点进flag.txt时&#xff0c;url变为 http://b9e52e06-e591-46ad-953e-7e8c5f…

银行卡的分类

银行卡是银行账户的一种体现形式&#xff0c;它是由银行机构发行的具有消费信用、转账结算、存取现金等全部或部分功能作为结算支付工具的各类卡的统称。 &#xff08;1&#xff09;按是否具有授信额度分类 ①借记卡&#xff1a;借记卡是指发卡银行向申请人签发的&#xff0c;没…

第十一章:位运算符与位运算

文章目录 第十一章&#xff1a;位运算符与位运算1.按位与运算&#xff1a;&2.按位或运算&#xff1a;|3.按位异或运算&#xff1a;^4.取反运算符&#xff1a;~5.左移运算符&#xff1a;<<6.右移运算符&#xff1a;>>总结 第十一章&#xff1a;位运算符与位运算…

动态内存操作函数使用过程中会遇见的问题

越界访问 首先我们上一个代码&#xff0c;看看这个的代码的问题 这个代码的问题显而易见 &#xff0c;就是在循环里面&#xff0c;产生了越界访问的问题&#xff0c;这里你开辟了10个整形空间&#xff0c;但是从0-10一共是11个整形空间。导致访问不合法的空间&#xff0c;从而…

Cy3-PEG-NH2 Cy3-聚乙二醇-氨基 磷脂PEG花菁Cy3

产品名称 Cy3-PEG-NH2 目录号 410502 中文名称 Cy3-聚乙二醇-氨基 英文名称 Cy3-PEG-NH2 Cy3-PEG-Amine 分子量 2000 溶解度 溶于氯仿等有机溶剂 存储条件 -20冷冻避光 保存时间 一年 Ex/Em(nm) 550/570 其它分子量 1000 3400 5000 10000 结构 花氰染料Cyanine,常应用…

记一次由gzip引起的nginx转发事故

故事背景 书接前几篇文章&#xff0c;仍然是交付甲方遇到的一个特殊诉求&#xff0c;从而引发了本期的事故。甲方的诉求是前端的请求过来&#xff0c;需要加密&#xff0c;但是要经过waf&#xff0c;必须要求是请求明文&#xff0c;那就要在waf和nginx之间做一个解密前置应用处…

搜索插入位置-java

题目描述 : 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 思路分析: 这段代码的解题思想是利用二分查找的方法在…

MySql实战--事务到底是隔离的还是不隔离的

第3篇文章和你讲事务隔离级别的时候提到过&#xff0c;如果是可重复读隔离级别&#xff0c;事务T启动的时候会创建一个视图read-view&#xff0c;之后事务T执行期间&#xff0c;即使有其他事务修改了数据&#xff0c;事务T看到的仍然跟在启动时看到的一样。也就是说&#xff0c…

深入探讨分布式ID生成方案

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

OSPF-区域间路由计算

一、概述 前面学习了我们学习了Router-LSA和Network-LSA&#xff0c;它们都只能在区域内进行泛洪&#xff0c;而且我们之前一直主要是单区域学习。OSPF的核心是骨干区域Area 0&#xff0c;其它都为非骨干区域。但是在大型网络中&#xff0c;单区域OSPF会存在一定的问题&#xf…