springboot基础
1. 快速入门
https://docs.spring.io/spring-boot/docs/
https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/html
https://developer.aliyun.com/mirror/mave
<?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.itheima</groupId>
<artifactId>springboot-helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
package com.itheima.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello springboot";
}
}
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class,args);
}
}
2. 配置文件
3. 读取配置文件
package com.itheima.springbootinit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Value("${name}")
private String name;
@Value("${person.name}")
private String name2;
@Value("${person.age}")
private int age;
@Value("${address[0]}")
private String address1;
@Value("${msg1}")
private String msg1;
@Value("${msg2}")
private String msg2;
@Autowired
private Environment env;
@Autowired
private Person person;
@RequestMapping("/hello2")
public String hello2() {
System.out.println(name);
System.out.println(name2);
System.out.println(age);
System.out.println(address1);
System.out.println(msg1);
System.out.println(msg2);
System.out.println("----------------------");
System.out.println(env.getProperty("person.name"));
System.out.println(env.getProperty("address[0]"));
System.out.println("-------------------");
System.out.println(person);
String[] address = person.getAddress();
for (String s : address) {
System.out.println(s);
}
return "hello Spring Boot 222!";
}
@RequestMapping("/hello")
public String hello() {
return "hello Spring Boot 222!";
}
}
@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
private String name;
private int age;
}
person:
name: abc
age: 20
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
package com.itheima.springbootinit;
@RestController
public class HelloController {
@Autowired
private Person person;
@RequestMapping("/hello2")
public String hello2() {
System.out.println(person);
String[] address = person.getAddress();
for (String s : address) {
System.out.println(s);
}
return "hello Spring Boot 222!";
}
}
4. profile
5. 内部配置加载顺序
注意:resource路径下为第4个
6. 整合junit
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
package com.itheima.springbootjunit;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void show(){
System.out.println("show....");
}
}
package com.itheima.test;
import com.itheima.springbootjunit.SpringbootJunitApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootJunitApplication.class )
public class UserServiceTest {
@Test
public void test(){
System.out.println(111);
}
}
7.整合mybatis
CREATE DATABASE /*!32312 IF NOT EXISTS*/`springboot` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
USE `springboot`;
/*Table structure for table `t_user` */
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*Data for the table `t_user` */
insert into `t_user`(`id`,`username`,`password`) values (1,'zhangsan','123'),(2,'lisi','234');
package com.itheima.springbootmybatis.domain;
import lombok.Data;
@Data
public class User {
private int id;
private String username;
private String password;
}
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima</groupId>
<artifactId>springboot-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--<scope>runtime</scope>-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
# datasource
spring:
datasource:
url: jdbc:mysql:///springboot?serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml # mapper映射文件路径
type-aliases-package: com.itheima.springbootmybatis.domain
# config-location: # 指定mybatis的核心配置文件
package com.itheima.springbootmybatis.mapper;
import com.itheima.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserMapper {
@Select("select * from t_user")
public List<User> findAll();
}
package com.itheima.springbootmybatis.mapper;
import com.itheima.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserXmlMapper {
public List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.springbootmybatis.mapper.UserXmlMapper">
<select id="findAll" resultType="user">
select * from t_user
</select>
</mapper>
package com.itheima.springbootmybatis;
import com.itheima.springbootmybatis.domain.User;
import com.itheima.springbootmybatis.mapper.UserMapper;
import com.itheima.springbootmybatis.mapper.UserXmlMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Autowired
private UserXmlMapper userXmlMapper;
@Test
public void testFindAll() {
List<User> list = userMapper.findAll();
System.out.println(list);
}
@Test
public void testFindAll2() {
List<User> list = userXmlMapper.findAll();
System.out.println(list);
}
}
8. 两步实现定时任务
8.1 添加注解@EnableScheduling
@SpringBootApplication
@EnableScheduling
public class springbootApplicationMybatis {
public static void main(String[] args) {
SpringApplication.run(springbootApplicationMybatis.class,args);
}
}
8.2 方法上添加注解@Scheduled()
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@SpringBootApplication
@EnableScheduling
public class springbootApplicationMybatis {
public static void main(String[] args) {
SpringApplication.run(springbootApplicationMybatis.class,args);
}
//1min 执行一次
@Scheduled(fixedRate = 1*60*1000)
public void play(){
System.out.println("hello sheduled");
}
//9-22点之间每隔30分钟提醒一次
@Scheduled(cron = "0 0/30 9-22 * * ?")
public void play2(){
System.out.println("hello sheduled");
}
}
在线生成cron表达式https://cron.qqe2.com/
注意:spring只支持前6个,不支持年
9. 异步实现定时任务
9.1 开启注解@EnableAsync
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class springbootApplicationMybatis {
public static void main(String[] args) {
SpringApplication.run(springbootApplicationMybatis.class,args);
}
//1min 执行一次
@Scheduled(fixedRate = 1*60*1000)
public void play(){
System.out.println("hello sheduled");
}
}
9.2 设置异步执行@Async
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class springbootApplicationMybatis {
public static void main(String[] args) {
SpringApplication.run(springbootApplicationMybatis.class,args);
}
//1min 执行一次
@Async
@Scheduled(fixedRate = 1000)
public void play(){
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("线程名称:"+Thread.currentThread().getName());
System.out.println("hello sheduled");
}
//9-22点之间每隔半小时提醒一次
@Async
@Scheduled(cron = "0 0/30 9-22 * * ?")
public void play2(){
System.out.println("hello sheduled");
}
}
10. 整合redis
10.1 本地redis服务
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
启动本地redis服务
package com.itheima;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.data.redis.core.RedisTemplate;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloApplicationTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void set(){
redisTemplate.boundValueOps("name").set("zhangsan");
}
@Test
public void get(){
Object name = redisTemplate.boundValueOps("name").get();
System.out.println(name);
}
}
10.2 非本地redis服务
server:
port: 8081
spring:
redis:
host: 127.0.0.1
port: 6379
其余与上述代码一致
11. springBoot 自动配置
11.1 condition
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
若在maven配置文件中导入了redis的坐标,则下列代码可以正确输出redisTemplate
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
//启动springboot应用,并返回spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
//获取bean,redisTemplate
Object redisTemplate = context.getBean("redisTemplate");
System.out.println(redisTemplate);
}
}
若没导入redis的坐标,则打印报错
package com.itheima.domain;
public class User {
}
package com.itheima.config;
import com.itheima.condition.ClassCondition;
import com.itheima.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();
}
}
package com.itheima.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) {
return true;
}
}
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
//启动springboot应用,并返回spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
//获取bean,redisTemplate
Object user = context.getBean("user");
System.out.println(user); //ClassCondition返回true,可以打印对象;返回false,打印报错
}
}
完善matches方法逻辑,即可实现上述案例要求
package com.itheima.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) {
try {
Class<?> clas = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
}
1)自定义注解的方式实现
package com.itheima.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.config;
import com.itheima.condition.ClassCondition;
import com.itheima.condition.ConditionOnClass;
import com.itheima.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();
}
}
package com.itheima.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 {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnClass.class.getName());
assert map != null;
String[] value = (String[]) map.get("value");
try {
for (String className : value) {
Class<?> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
}
2)springboot提供的注解实现
package com.itheima.config;
import com.itheima.condition.ClassCondition;
import com.itheima.condition.ConditionOnClass;
import com.itheima.domain.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
@ConditionalOnProperty(name = "itcast",havingValue = "itheima") // 只有配置文件中有这个键值对,才加载这个bean
public User user2(){
return new User();
}
@Bean
@ConditionalOnClass(name = "redis.clients.jedis.Jedis") // springboot提供的注解
public User user3() {
return new User();
}
}
11.2 切换内置web服务器
内置四个web服务器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
注意:排除依赖,最好clean一下项目,否则可能会导致失效
11.3 @Enable*注解
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注
解导入一些配置类,实现Bean的动态加载
spring boot不能直接获取其它工程定义的bean
解决方案1:
解决方案2:
解决方案3:
11.4 @Import注解
@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用
法:
① 导入Bean
② 导入配置类
③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类
④ 导入 ImportBeanDefiniti onRegistrar 实现类。
11.5 EnableAutoConfiguration
11.6 自定义starter实现
1)autoconfigure模块
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--引入jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
package com.nbcb.config;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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 {
@Bean
@ConditionalOnMissingBean(name = "jedis")
public Jedis jedis(RedisProperties redisProperties) {
System.out.println("ConditionalOnMissingBean");
return new Jedis(redisProperties.getHost(), redisProperties.getPort());
}
}
package com.nbcb.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;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com/nbcb/config/RedisAutoConfiguration
2)starter模块
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--引入自定义的configure-->
<dependency>
<groupId>com.nbcb</groupId>
<artifactId>redis-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
3)测试模块
<dependency>
<groupId>com.nbcb</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);
String name = jedis.get("name");
System.out.println(name);
}
// @Bean
// public Jedis jedis(){
// return new Jedis("localhost",6379);
// }
}
redis:
port:
6666
12.springBoot 监听机制
12.1 事件监听
package com.nbcb.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");
}
}
package com.nbcb.listener;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
//当项目启动后执行run方法,可以在项目启动后加载一些redis缓存
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner... run");
}
}
package com.nbcb.listener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
//当项目启动后执行run方法,可以在项目启动后加载一些redis缓存
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner....run");
}
}
package com.nbcb.listener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;
//@Component
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
public MySpringApplicationRunListener(SpringApplication application, String[] args) {
}
@Override
public void starting() {
System.out.println("starting...项目启动中");
}
@Override
public void environmentPrepared(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....项目启动失败");
}
}
org.springframework.context.ApplicationContextInitializer=com.nbcb.listener.MyApplicationContextInitializer
org.springframework.boot.SpringApplicationRunListener=com.nbcb.listener.MySpringApplicationRunListener
13.springBoot监控
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
http://localhost:8080/actuator
info.name=zhangsan
management.endpoint.health.show-details=always
14. springBoot项目部署
<groupId>com.nbcb</groupId>
<artifactId>springboot-listener</artifactId>
<packaging>war</packaging>
package com.nbcb.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/hello")
@RestController
public class HelloSpringBoot {
@RequestMapping("/findAll")
public String findAll(){
return "success";
}
}
package com.nbcb;
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;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class HelloApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(HelloApplication.class);
}
}
注:使用maven打包,然后将打包的war包放入外部的tomcat的webapp路径下即可
15. springboot构建多个modules
<?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>org.springframework.boot</groupId>
<artifactId>springboot-modules</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module-common</module>
<module>test1</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.boot.verison>2.1.8.RELEASE</spring.boot.verison>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.verison}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.verison}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?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>org.springframework.boot</groupId>
<artifactId>springboot-modules</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>module-common</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.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
16. 数据库密码加密
16.1 导包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
16.2 使用测试类生成密钥
@Test
public void druidEncrypt() throws Exception {
//密码明文
String password = "root";
System.out.println("明文密码: " + password);
String[] keyPair = ConfigTools.genKeyPair(512);
//私钥
String privateKey = keyPair[0];
//公钥
String publicKey = keyPair[1];
//用私钥加密后的密文
password = ConfigTools.encrypt(privateKey, password);
System.out.println("privateKey:" + privateKey);
System.out.println("publicKey:" + publicKey);
System.out.println("加密password:" + password);
String decryptPassword = ConfigTools.decrypt(publicKey, password);
System.out.println("解密后:" + decryptPassword);
}
生成公钥和私钥,还可使用命令生成:java -cp druid-1.1.10.jar com.alibaba.druid.filter.config.ConfigTools you_password
注意:加密password和密钥,每次加密都会变,需要成对使用
16.3 数据库配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ66HTZjbCuDU+Fymehr9lqBIjx0ojdt99LorR3pn6hyTy/nmnrGCO3fY2F3MgErluehKgjZGin9FnXO9M6xiU0CAwEAAQ==
druid:
url: jdbc:mysql:///springboot?serverTimezone=UTC
username: root
password: CsyerNasXVUJ5zoBXWjJ/gp/ylEUF2m22RmMivye/Z8wLYQBEdNxNfcLKP2NRUFYcVPSXYftJ2oEB0wkszEx9A==
filter:
config:
enabled: true
connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publicKey}
17. 文件上传与下载
17.1 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.1</version>
</dependency>
</dependencies>
17.2 application.properties
# 默认开启
pring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=20MB
spring.servlet.multipart.max-request-size=20MB
file.upload.path=d:/test
file.upload.type=dll,exe
17.3 Controller
package com.nbcb.controller;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("file")
@Slf4j
public class FileController {
@Value("${file.upload.path}")
private String uploadFilePath;
@RequestMapping(value = {"", "/", "/index"})
public String index() {
return "upload";
}
@ResponseBody
@PostMapping("/uploadFile")
public String fileUpload(@RequestParam("file") MultipartFile file) {
JSONObject result = new JSONObject();
if (file.isEmpty()) {
result.put("error", "文件上传失败");
return result.toString();
}
String fileName = file.getOriginalFilename();
assert fileName != null;
String suffixName = fileName.substring(fileName.lastIndexOf("."));
log.info("上传文件名称为{},后缀名为{}", fileName, suffixName);
File fileTempObj = new File(uploadFilePath + File.separator + fileName);
if (!fileTempObj.getParentFile().exists()) {
fileTempObj.getParentFile().mkdirs();
}
if (fileTempObj.exists()) {
result.put("error", "文件已经存在");
return result.toString();
}
try {
// 写入文件方式1:
// file.transferTo(fileTempObj);
//写入方式2:
FileUtil.writeBytes(file.getBytes(), fileTempObj);
} catch (IOException e) {
log.error("发生错误{}", e.getMessage());
result.put("error", e.getMessage());
return result.toString();
}
result.put("success", "文件上传成功");
return result.toString();
}
@ResponseBody
@RequestMapping("/downloadFile")
public String fileDownload(HttpServletResponse response, @RequestParam("fileName") String fileName) throws IOException {
JSONObject result = new JSONObject();
File file = new File(uploadFilePath + File.separator + fileName);
if (!file.exists()) {
result.put("error", "文件不存在");
return result.toString();
}
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//方式1
// byte[] bytes = FileCopyUtils.copyToByteArray(file);
//方式2
byte[] bytes = FileUtil.readBytes(file);
response.getOutputStream().write(bytes);
result.put("success","文件下载成功");
return result.toString();
}
}