SpringBoot高级
1.SpringBoot原理分析
1.1 自动配置
1.Condition
Condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作
思考:SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?
package com.itheima.springbootcondition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootConditionApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args);
//获取Bean,redisTemplate
Object redisTemplate = context.getBean("redisTemplate");
System.out.println(redisTemplate);
}
}
案例:需求
-
在Spring的IOC容器中有一个User的bean,现要求:
- 导入Jedis坐标后,加载该bean,没有导入,则不加载
- 将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定
实现操作:
-
创建User类
-
user配置类
package com.itheima.springbootcondition.config; import com.itheima.springbootcondition.condition.ClassCondition; import com.itheima.springbootcondition.domain.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class UserConfig { @Bean @Conditional(ClassCondition.class) public User user() { return new User(); } }
-
condition条件类
package com.itheima.springbootcondition.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class ClassCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //1.需求:导入jedis坐标后,创建bean //思路:判断redis.clients.jedis.Jedis.class文件是否存在 boolean flag = true; try { Class cls = Class.forName("redis.clients.jedis.Jedis"); } catch (ClassNotFoundException e) { flag = false; } return flag; } }
-
引导类
package com.itheima.springbootcondition; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class SpringbootConditionApplication { public static void main(String[] args) { //启动SpringBoot的应用,返回Spring的IOC容器 ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args); //获取Bean,redisTemplate // Object redisTemplate = context.getBean("redisTemplate"); // System.out.println(redisTemplate); Object user = context.getBean("user"); System.out.println(user); } }
动态判断加载bean
-
自定义条件注解
package com.itheima.springbootcondition.condition; import org.springframework.context.annotation.Conditional; import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(ClassCondition.class) public @interface ConditionOnClass { String[] value(); }
-
条件类
package com.itheima.springbootcondition.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import java.util.Map; public class ClassCondition implements Condition { /** * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象 * @param metadata 注解元对象。可以获取注解定义的属性值 * @return */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { /* //1.需求:导入jedis坐标后,创建bean //思路:判断redis.clients.jedis.Jedis.class文件是否存在 boolean flag = true; try { Class cls = Class.forName("redis.clients.jedis.Jedis"); } catch (ClassNotFoundException e) { flag = false; } return flag; */ //2.需求:导入通过注解属性值value指定坐标后,创建bean //获取注解属性值 Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName()); // System.out.println(map); String[] value = (String[]) map.get("value"); boolean flag = true; try { for (String className : value) { Class cls = Class.forName(className); } } catch (ClassNotFoundException e) { flag = false; } return flag; } }
-
配置类(创建指定类bean对象)
package com.itheima.springbootcondition.config; import com.itheima.springbootcondition.condition.ConditionOnClass; import com.itheima.springbootcondition.domain.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class UserConfig { @Bean // @Conditional(ClassCondition.class) @ConditionOnClass("redis.clients.jedis.Jedis") public User user() { return new User(); } }
-
SpringBoot提供的常用条件注解:
ConditionalOnClass:判断环境中有指定class时才初始化bean
ConditionalOnProperty:判断配置文件是否有指定键值对时才初始化bean
ConditionalOnMissingClass:没有有指定class时才初始化bean
ConditionalOnMissingBean:判断环境中没有有指定bean时才初始化bean
2.切换内置web服务器
SpringBoot的web环境默认使用tomcat作为内置服务器,其实SpringBoot提供了4种内置服务器供我们使用,我们可以很方便的进行切换
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
3.@Enable*注解
SpringBoot中提供了很多Enable开头的注解,这些注解都是动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载
思考:SpringBoot工程是否可以直接获取jar包中定义的Bean?
操作实现:
-
启动类:
package com.itheima.springbootenable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; /** * @ComponentScan 扫面范围:当前引导类所在包及其子包 * * com.itheima.springbootenable * com.itheima.config * //1.使用@ComponentScan扫描com.itheima.config包 * //2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器 * //3.使用自定义@EnableUser注解 */ @SpringBootApplication //@ComponentScan("com.itheima.config") //@Import(UserConfig.class) //@EnableUser public class SpringbootEnableApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args); //获取bean Object user = context.getBean("user"); System.out.println(user); } }
-
自定义注解@EnableUser
package com.itheima.config; import org.springframework.context.annotation.Import; import java.lang.annotation.*; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(UserConfig.class) public @interface EnableUser { }
-
配置类:
package com.itheima.config; import com.itheima.domain.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class UserConfig { @Bean public User user() { return new User(); } }
4.@Import注解
@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4种用法:
- 导入Bean
- 导入配置类
- 导入ImportSelector实现类。一般用于加载配置文件中的类
- 导入ImportBeanDefinitionRegistrar实现类
实现代码
-
引导类:
package com.itheima.springbootenable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; /** * @ComponentScan 扫面范围:当前引导类所在包及其子包 * * com.itheima.springbootenable * com.itheima.config * //1.使用@ComponentScan扫描com.itheima.config包 * //2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器 */ /** * 1. 导入Bean * 2. 导入配置类 * 3. 导入ImportSelector实现类。一般用于加载配置文件中的类 * 4. 导入ImportBeanDefinitionRegistrar实现类 */ @SpringBootApplication //@ComponentScan("com.itheima.config") //@Import(UserConfig.class) //@EnableUser //@Import(User.class) //@Import(UserConfig.class) //@Import(MyImportSelctor.class) //@Import(MyImportBeanDefinitionRegistrar.class) public class SpringbootEnableApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args); //获取bean // Object user = context.getBean("user"); // System.out.println(user); // User user = context.getBean(User.class); // System.out.println(user); // // Role role = context.getBean(Role.class); // System.out.println(role); Object user = context.getBean("user"); System.out.println(user); } }
-
自定义ImportSelector实现类方式加载bean
package com.itheima.config; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.itheima.domain.User","com.itheima.domain.Role"}; } }
-
自定义ImportBeanDefinitionRegistrar实现类方式加载bean
package com.itheima.config; import com.itheima.domain.User; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AbstractBeanDefinition bean = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition(); registry.registerBeanDefinition("user",bean); } }
5.@EnableAutoConfiguration注解
- @EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置类
- 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean
- 并不是所有Bean都会被初始化,在配置类中Condition来加载满足条件的Bean
6.案例
需求:自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean
实现步骤:
- 创建redis-spring-boot-autoconfigure模块
- 创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure模块
- 在redis-spring-boot-autoconfigure模块中初始化Jedis的Bean。并定义META-INF/spring.factories文件
- 在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis
实现操作:
-
redis-spring-boot-autoconfigure模块
redis自动加载配置类:
package com.itheima.redis.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import redis.clients.jedis.Jedis; @Configuration @EnableConfigurationProperties(RedisProperties.class) @ConditionalOnClass(Jedis.class) public class RedisAutoConfiguration { /** * 提供jedis的bean */ @Bean @ConditionalOnMissingBean(name = "jedis") public Jedis jedis(RedisProperties redisProperties) { System.out.println("RedisAutoConfiguration....."); return new Jedis(redisProperties.getHost(),redisProperties.getPort()); } }
redis配置对象类:
package com.itheima.redis.config; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "redis") public class RedisProperties { private String host = "localhost"; private int port = 6379; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }
配置文件resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.itheima.redis.config.RedisAutoConfiguration
依赖引入
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--引入jedis依赖--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> </dependencies>
-
redis-spring-boot-starter模块
依赖引入
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--引入configure--> <dependency> <groupId>com.itheima</groupId> <artifactId>redis-spring-boot-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
-
测试模块springboot-enable
依赖引入
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.itheima</groupId> <artifactId>springboot-enable-condition</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--mybatis起步依赖--> <!-- <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency>--> <!--redis自定义的starter--> <dependency> <groupId>com.itheima</groupId> <artifactId>redis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
引导类:
@SpringBootApplication //@ComponentScan("com.itheima.config") //@Import(UserConfig.class) //@EnableUser //@Import(User.class) //@Import(UserConfig.class) //@Import(MyImportSelctor.class) //@Import(MyImportBeanDefinitionRegistrar.class) @Import(Jedis.class) public class SpringbootEnableApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args); //获取bean // Object user = context.getBean("user"); // System.out.println(user); // User user = context.getBean(User.class); // System.out.println(user); // // Role role = context.getBean(Role.class); // System.out.println(role); // Object user = context.getBean("user"); // System.out.println(user); Jedis jedis = context.getBean(Jedis.class); System.out.println(jedis); jedis.set("name","itcast"); String name = jedis.get("name"); System.out.println(name); } }
1.2 监听机制
Java监听机制
SpringBoot的监听机制,其实是对Java提供的事件监听机制的封装
Java中事件监听机制定义了以下几个角色:
- 事件:Event,继承java.util.EventObject类的对象
- 事件源:Source,任意对象Object
- 监听器:LIstener,实现java.util.EventListener接口的对象
SpringBoot监听机制
SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作
ApplicationContextInitializer、SpringApplicationRunListener、CommandLineRunner、ApplicationRunner
实现操作:
-
ApplicationContextInitializer实现类
package com.itheima.springbootlistener.listener; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.stereotype.Component; @Component public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("ApplicationContextInitializer... initialize"); } }
-
SpringApplicationRunListener实现类
package com.itheima.springbootlistener.listener; import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplicationRunListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; public class MySpringApplicationRunListener implements SpringApplicationRunListener { public MySpringApplicationRunListener(SpringApplication application,String[] args) { } @Override public void starting(ConfigurableBootstrapContext bootstrapContext) { System.out.println("starting...项目启动中"); } @Override public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) { System.out.println("environmentPrepared...环境对象开始准备"); } @Override public void contextPrepared(ConfigurableApplicationContext context) { System.out.println("contextPrepared...上下文对象开始准备"); } @Override public void contextLoaded(ConfigurableApplicationContext context) { System.out.println("contextLoaded...上下文对象开始加载"); } @Override public void started(ConfigurableApplicationContext context) { System.out.println("started...上下文对象加载完成"); } @Override public void running(ConfigurableApplicationContext context) { System.out.println("running...项目启动完成,开始运行"); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { System.out.println("failed...项目启动失败"); } }
-
ApplicationRunner实现类
package com.itheima.springbootlistener.listener; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import java.util.Arrays; /** * 当项目启动后执行run方法 */ @Component public class MyApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunner... run"); System.out.println(Arrays.asList(args.getSourceArgs())); } }
-
CommandLineRunner实现类
package com.itheima.springbootlistener.listener; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.util.Arrays; @Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("CommandLineRunner.... run"); System.out.println(Arrays.asList(args)); } }
-
配置文件src/main/resources/META-INF/spring.factories
org.springframework.context.ApplicationContextInitializer=\ com.itheima.springbootlistener.listener.MyApplicationContextInitializer org.springframework.boot.SpringApplicationRunListener=\ com.itheima.springbootlistener.listener.MySpringApplicationRunListener
-
启动类
package com.itheima.springbootlistener; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringbootListenerApplication { public static void main(String[] args) { SpringApplication.run(SpringbootListenerApplication.class, args); } }
-
运行结果:
starting…项目启动中
environmentPrepared…环境对象开始准备. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.5)
:: Spring Boot :: (v2.4.5)
ApplicationContextInitializer… initialize
contextPrepared…上下文对象开始准备
2021-05-08 17:43:47.683 INFO 5988 — [ main] c.i.s.SpringbootListenerApplication : Starting SpringbootListenerApplication using Java 1.8.0_271 on Boristang with PID 5988 (E:\Date\SpringBoot\springboot\springboot-listener\target\classes started by 11712 in E:\Date\SpringBoot\springboot\springboot-enable)
2021-05-08 17:43:47.696 INFO 5988 — [ main] c.i.s.SpringbootListenerApplication : No active profile set, falling back to default profiles: default
contextLoaded…上下文对象开始加载
2021-05-08 17:43:49.162 INFO 5988 — [ main] c.i.s.SpringbootListenerApplication : Started SpringbootListenerApplication in 2.537 seconds (JVM running for 6.086)
started…上下文对象加载完成
ApplicationRunner… run
[name=itcast]
CommandLineRunner… run
[name=itcast]
running…项目启动完成,开始运行Process finished with exit code 0
1.3 启动流程分析
启动流程
2.SpringBoot监控
2.1 概述
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等
2.2 监控使用
使用步骤
-
导入依赖坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
访问httpp://localhost:8080/actuator
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"health-path":{"href":"http://localhost:8080/actuator/health/{*path}","templated":true},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"info":{"href":"http://localhost:8080/actuator/info","templated":false}}}
2.3 开启所有endpoint
info.name=zhangsan
info.age=20
# 开启健康检查的完整信息
management.endpoint.health.show-details=always
# 将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*
2.4 Spring Boot Admin
- Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序
- Spring Boot Admin有两个角色,客户端(Client)和服务端(Server)
- 应用程序作为Spring Boot Admin Client向Spring Boot Admin Server注册
- Spring Boot Admin Server的UI界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息
使用步骤:
admin-server:
- 创建admin-server模块
- 导入依赖坐标admin-starter-server
- 在引导类上启用监控功能@EnableAdminServer
admin-client:
- 创建admin-client模块
- 依赖坐标admin-starter-client
- 配置相关信息:server地址等
- 启动server和client服务,访问server
实现操作:
-
创建springboot-admin-server模块
配置文件application.properties
server.port=9000
-
创建springboot-admin-client模块
配置文件application.properties
# 执行admin,server地址 spring.boot.admin.client.url=http://localhost:9000 # management.endpoint.health.show-details=always management.endpoints.web.exposure.include=*
-
启动server模块,再启动client模块
-
访问URL:http://localhost:9000/
-
在client模块添加控制器类
package com.itheima.springbootadminclient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @RequestMapping("/findAll") public String findAll() { return "success"; } }
-
访问该资源后,使用spring boot admin查看
3.SpringBoot项目部署
3.1 打包方式
SpringBoot项目开发完毕后,支持两种方式部署到服务器:
- jar包(官方推荐)
- war包
3.2 jar包
jar包(默认打包方式)
实现操作:
-
创建新的模块springboot-deploy
-
创建一个控制类,添加访问资源
package com.itheima.springbootdeploy; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @RequestMapping("/findAll") public String findAll() { return "success"; } }
-
打包(默认jar包)
-
cmd命令运行jar包(jar包位置target目录下,此处将之复制到桌面project下)
-
访问测试
3.3 war包
实现操作:
-
修改maven配置文件,如有packaging标签,则将jar改为war,若没有则添加
<packaging>war</packaging>
-
修改启动类,使之继承SpringBootServletInitializer并重写configure方法
package com.itheima.springbootdeploy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication public class SpringbootDeployApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringbootDeployApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return super.configure(builder); } }
-
可给包命名,在maven配置文件build标签下添加如下内容:
<finalName>springboot</finalName>
-
打包
-
运行启动项目(将war包复制到本地tomcat服务器webapps目录下,进入bin目录运行startup.bat)
-
访问测试
- 注意:内置tomcat配置不生效,需修改外部tomcat配置
上一篇:SpringBoot基础
相关文章:SpringBoot基础、SpringBoot高级