模拟springboot底层实现自己自定义custom的springboot单jar工程应用,Embedded Tomcat9使用

springboot已经深入人心,免去繁琐的xml配置,用着得心应手,但是你知道它是怎么运行起来的呢?如何嵌入Embedded Tomcat的呢?本文单一的main方法,教你实现自己的springboot
自己实现springboot
在这里插入图片描述
在这里插入图片描述
maven项目

//pom.xml
<?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>

    <groupId>com.ddddd</groupId>
    <artifactId>springboottest3</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>9.0.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>tttt.Test</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
//Test.java
package tttt;

import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import java.io.File;

/**
 * @author zhanghui
 * @date 2019/6/26
 */
public class Test {

    public static void main(String[] args) {
        System.out.println("current working dir:"+System.getProperty("user.dir")+File.separator);

        Tomcat tomcat = new Tomcat();

        // tomcat config

        //CATALINA_BASE home dir
        String baseDir = "./tomcat_tmp/";
        tomcat.setBaseDir(baseDir);
        tomcat.setPort(8080);
        tomcat.setHostname("127.0.0.1");  //default localhost

        // tomcat component config, server->service->connector->engine->host->context

        Server    server    = tomcat.getServer();   //one server for one tomcat
        Service   service   = tomcat.getService();
        Connector connector = tomcat.getConnector();  // default HTTP/1.1 connector
        Engine    engine    = tomcat.getEngine();
        Host      host      = tomcat.getHost();
        Context  context    = tomcat.addContext(host,"","../"); // dir is "", means create webapps dir under baseDir


        // servlet config

        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.scan("myapp");

        String servletName = "myspringmvc";
        Tomcat.addServlet(context,servletName,new DispatcherServlet(appContext));
        context.addServletMappingDecoded("/*",servletName);


        try {
            tomcat.start();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }

        tomcat.getServer().await();
    }
}

//TestController.java
package myapp.controller;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * @author zhanghui
 * @date 2019/7/3
 */
@RestController
public class TestController {

    @GetMapping({"","/"})
    public String hi(){
        return "hi";
    }


    // default not mapping url
    @GetMapping("/**")
    public String defaultPage(HttpServletRequest request){
        StringBuilder stringBuilder = new StringBuilder(request.getRequestURL().toString());
        if(!StringUtils.isEmpty(request.getQueryString()))
            stringBuilder.append("?" + request.getQueryString());

        return "defaultPage:"+ stringBuilder.toString();
    }
}

manven打包package后,springboottest3-1.0-jar-with-dependencies.jar
java -jar D:\proj\springboottest3\target\springboottest3-1.0-jar-with-dependencies.jar

牛逼不?点赞,评论,关注,是对我最大的肯定,谢谢
我爱你-熊本熊

后记:加入jdbc查询

//pom.xml
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jdbc</artifactId>
            <version>1.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
//DbConfig.java
package myapp.controller;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * @author zhanghui
 * @date 2019/6/20
 */
@Configuration
public class DbConfig {


    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://192.168.1.196:3306?useSSL=false");
        dataSource.setUsername("");
        dataSource.setPassword("");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");

        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbc(){
        return new JdbcTemplate(dataSource());
    }


}

//TestController.java
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("/jdbc")
    public String jdbc(){
        jdbcTemplate.execute("use voice_robot");
        List<Map<String, Object>> ress = jdbcTemplate.queryForList("show tables");

        System.out.println(ress.size());

        return "jdbc";
    }

后记2:log4j2日志,很像springboot日志
log4j2日志

//pom.xml
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.11.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.12</version>
        </dependency>
//Test.java  有main方法的类内,静态块,初始化日志配置
static {
        ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

        AppenderComponentBuilder console = builder.newAppender("stdout", "Console");
        LayoutComponentBuilder standard = builder.newLayout("PatternLayout");
        standard.addAttribute("disableAnsi",false);
        // %c{2.} short class name, %c{36} whole class name
        standard.addAttribute("pattern", "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} %style{%pid}{magenta} [%15.15t] %style{%-40.40C{1.}}{cyan} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}");
        console.add(standard);
        builder.add(console);


        RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.ALL);
        rootLogger.add(builder.newAppenderRef("stdout"));
        builder.add(rootLogger);

        LoggerComponentBuilder logger = builder.newLogger("com", Level.DEBUG);
        logger.add(builder.newAppenderRef("stdout"));
        logger.addAttribute("additivity", false);
        builder.add(logger);

        Configurator.initialize(builder.build());
    }
//TestController.java
@Slf4j
@RestController
public class TestController {


//看看日志效果
log.error("jdbc...........................");

后记3:加入spring session
spring-session
【spring session的实现方式】
tomcat加入一个DelegatingFilterProxy的filter,这个只是一个filter的代理,由他接管,当tomcat调用filter时,就会调用这个代理,然后这个代理会在spring中找以他的FilterName定义的bean,这个bean就是真正的filter (SessionRepositoryFilter),这个filter会替换掉原来的HTTPSession为HttpSessionWrapper,HttpSessionWrapper实现将session写入redis

//pom.xml
<dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>2.1.5.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
//RedisConfig.java
package myapp.controller;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;

import javax.servlet.Filter;

/**
 * @author zhanghui
 * @date 2019/7/3
 */
@Configuration
public class RedisConfig {


    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName("192.168.1.196");
        factory.setPort(6379);
        return factory;
    }

    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        return redisTemplate;
    }

    @Bean("springSessionRepositoryFilter")
    public Filter delegatingFilterProxy(RedisTemplate<Object,Object> redisTemplate){
        return new SessionRepositoryFilter(new RedisOperationsSessionRepository(redisTemplate));
    }
}

//Test.java  配置tomcat加入filter
import org.springframework.web.filter.DelegatingFilterProxy;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;

        FilterDef filter1definition = new FilterDef();
        filter1definition.setFilterName("springSessionRepositoryFilter");
        filter1definition.setFilterClass(DelegatingFilterProxy.class.getName());
        context.addFilterDef(filter1definition);

        FilterMap filter1mapping = new FilterMap();
        filter1mapping.setFilterName("springSessionRepositoryFilter");
        filter1mapping.addURLPattern("/*");
        context.addFilterMap(filter1mapping);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值