手写SpringBoot(一)之简易版SpringBoot

简介: Configuration 注解表明该注解标注的类是一个配置类,在AnnotationConfigApplication 里面会解析这个类,并加载相应的容器beanCompontScan 注解定义Configuration配置类下的扫描路径,如果不传,默认扫描标注类的包名。所以SpringBoot默认会扫描Application类下的当前包以及子包路径。

手写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定义的路径地址,扫描组件注入到容器中。

这里由于MySpringBootApplication注解是一个组合注解,包括@Configuration和@ComponentScan,Spring在获取到@MySpringBootApplication标注的类,会默认将该类作为配置类,所以这个@MySpringBootApplication不一定非得加到Application类上,可以专门定义一个Configuration类来标注,但是需要将该类Class作为参数传给MySpringApplication.run方法中。

由于@Component默认会扫描被该注解标注的类的当前包路径作为默认扫描路径。所以@MySpringBootApplication标注的类的包路径需要注意。

启动tomcat


3.启动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 {


    @Resource
    private 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换成jetty或者是underTow容器怎么实现呢?

目录
相关文章
|
7月前
|
消息中间件 存储 安全
RabbiMQ原理与SpringBoot使用
RabbiMQ原理与SpringBoot使用
54 0
|
7月前
|
XML 开发框架 Java
【SpringBoot】什么是SpringBoot?简析SpringBoot
【SpringBoot】什么是SpringBoot?简析SpringBoot
33 1
|
Java
学习Springboot框架一 之最简单的Springboot项目
学习Springboot框架一 之最简单的Springboot项目
72 0
|
Java 调度 Spring
SpringBoot与任务(十一)
SpringBoot与任务(十一)
104 0
SpringBoot与任务(十一)
|
XML 前端开发 Java
手写SpringBoot框架
1、什么是SpringBoot框架。 SpringBoot是一个快速整合第三方框架;简化xml配置,完全采用注解化;内置http服务器(jetty和tomcat) ,最终是以java应用程序执行。 注
176 0
|
XML 监控 前端开发
SpringBoot——入门案例之“Hello SpringBoot“
SpringBoot——入门案例之“Hello SpringBoot“
SpringBoot——入门案例之“Hello SpringBoot“
|
JSON IDE Java
【SpringBoot2】快速上手SpringBoot
SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。SpringBoot 是 Spring 项目中的一个子工程,也被称为搭建程序的脚手架,可以快速的构建spring项目。
258 0
【SpringBoot2】快速上手SpringBoot
|
Web App开发 监控 前端开发
SpringBoot2.x系列教程05--SpringBoot花样配置之实现热部署配置及原理
前言 上一章节中,壹哥 带各位学会了配置自定义的Web端口与项目根目录,今天我们再来看看其他的一些小花样。 在开发阶段,我们编写完代码后,就得需要点击启动按钮,重启项目后才能看到更新后的内容,每次都这么操作,就会就得有点麻烦,那能不能让项目随着代码的更新而自动重启呢? 既然有了这样的需求,SpringBoot就很暖心的给我们提供了这样的功能。今天我们就来看看SpringBoot中的另一个小花样配置---实现SpringBoot项目的热加载。 注意 网上也有不少教程把该功能称为热部署,我觉得叫做热加载更准确点! 一. SpringBoot热加载简介 在SpringBoot中实现热加载相对来说
360 0
|
安全 Java 数据安全/隐私保护
SpringBoot学习笔记-13:第十三章-SpringBoot 与安全
SpringBoot学习笔记-13:第十三章-SpringBoot 与安全
128 0