文章目录

  • 一、SpringBoot快速入门
    • 1.1 快速搭建
    • 1.2 SpringBoot依赖引入
    • 1.3 RestController的使用
    • 1.4 SpringBoot启动方式
  • 二、SpringBoot整合Web开发
    • 2.1 springboot整合静态资源访问
    • 2.2 yml与properties格式区别
    • 2.3 Springboot整合freemarker模板引擎
    • 2.4 freemarker模板引擎条件判断用法
    • 2.5 thymeleaf渲染web界面
    • 2.6 解决thymeleaf误报问题
    • 2.7 thymeleaf循环和if判断写法
  • 三、整合数据库访问层
    • 1.整合JDBC
    • 2.Druid数据源
    • 3.整合Mybatis框架查询
    • 4.整合redis插入、查询、修改、删除操作
  • 四、整合Swagger接口文档
    • 4.1 引入依赖
    • 4.2 SwaggerConfig配置类
  • 五、整合热部署框架
    • 5.1 整合devtools工具
    • 5.2 整合Lombok简化代码
  • 六、整合读取配置文件
    • 6.1 使用@value注解读取配置文件
    • 6.2 properties转换yml格式
    • 6.3 @ConfigurationProperties
    • 6.4 整合多环境下不同配置文件
    • 6.5 修改端口号和上下文路径
  • 七、整合日志框架
    • 7.1 logback配置日志级别
    • 7.2 整合log4j2日志
  • 八、整合定时任务
    • 8.1 使用创建定时任务
    • 8.2 定时任务
  • 九、整合多线程异步
    • 9.1 使用@Async实现异步调用
    • 9.2 @Async失效问题
    • 9.3 @Async整合线程池
  • 十、SpringBoot文件上传
    • 10.1 文件上传
    • 10.1 文件下载
  • 十一、项目打包部署
    • 11.1 整合全局捕获异常
    • 11.2 打包运行发布

一、SpringBoot快速入门

1.1 快速搭建

开发工具:IDEA、JDK1.8
1.New Project->Spring Initializr

2.选择相关依赖->finish

3.新建一个controller包,在包下新建一个IndexController类

@RestController
public class IndexController {@RequestMapping("/hello")public String Hello(){return "学习SpringBoot快速入门";}
}

4.启动主类

5.访问8080端口,http://localhost:8080/hello

1.2 SpringBoot依赖引入

 <dependencies>#引入后在声明其他dependency时不需要version<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version></dependency>#spring-boot-starter-web已经整合好SpringMVC框架<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>#spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency>#引入Lombok<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

1.3 RestController的使用

1.如果在类上加上@RestController,该类中所有SpringMVC URL接口映射都是返回json格式
2.@RestController是我们SpringMVC提供 而不是Springboot提供
3. Rest 微服务接口开发中 Rest风格 数据传输格式json格式 协议http协议
4.Controller 控制层注解SpringMVC url接口映射默认的情况下返回页面跳转 如果需要返闯json格式的情况下需要ResponseBody注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {@AliasFor(annotation = Controller.class)String value() default "";
}

1.4 SpringBoot启动方式

方式一

@RestController
public class IndexController {@RequestMapping("/hello")public String Hello(){return "学习SpringBoot快速入门";}public static void main(String[] args) {SpringApplication.run(SpringbootLearnApplication.class,args);}
}

方式二

@Controller
@EnableAutoConfiguration
public class IndexController {@RequestMapping("/hello")@ResponseBodypublic String Hello(){return "学习SpringBoot快速入门";}public static void main(String[] args) {SpringApplication.run(SpringbootLearnApplication.class,args);}
}

方式三

@Controller
@EnableAutoConfiguration
//根据定义的扫描路径,把符合扫描规则的类装配到spring容器中
@ComponentScan("com/example/springbootlearn/controller")
public class IndexController {@RequestMapping("/hello")@ResponseBodypublic String Hello(){return "使用ComponentScan";}public static void main(String[] args) {SpringApplication.run(SpringbootLearnApplication.class,args);}
}

方式四

@RestController
public class IndexController {@RequestMapping("/hello")public String Hello(){return "SpringBoot启动";}
}
@SpringBootApplication
public class SpringbootLearnApplication {public static void main(String[] args) {SpringApplication.run(SpringbootLearnApplication.class, args);}}

SpringBootApplication开启自动配置,扫描同级包或子包

二、SpringBoot整合Web开发

Configurable
public class WebMvcConfig  extends WebMvcConfigurerAdapter {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");if(!registry.hasMappingForPattern("/**")){registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}super.addResourceHandlers(registry);}
}

2.1 springboot整合静态资源访问

可以在src/main/resources/目录下创建static,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/NBA_logo.jpg。如能显示图片,配置成功。

2.2 yml与properties格式区别

SpringBoot支持两种配置方式,一种是properties文件,一种是yml。
使用yml可以减少配置文件的重复性。
例如:application.properties

tgxit.name=taotao
tgxit.age=18

controller包下新建一个类UserController

@RestController
public class UserController {@Value("${tgxit.name}")private String name;@Value("${tgxit.age}")private String age;@RequestMapping("/getProp")public String getProp(){return name+"--"+age;}
}

访问http://localhost:8080/getProp,返回结果值taotao–18

新建一个application.yml

#注意yml语法格式,冒号':'后面又有空格,不加空格会造成值不生效
tgxit:name: xiaohuihuiage: 22

再加载主类进行测试,返回结果xiaohuihui–22

2.3 Springboot整合freemarker模板引擎

引入freemarker依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

编写freemarkerIndex.ftl

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"/><title></title>
</head>
<body>
${name}
</body>
</html>

编写Controller类

@Controller
public class FreemarkerController {@RequestMapping("/freemarkerIndex")@ResponseBodypublic String freemarker(Map<String,String > result){result.put("name","blackhorse");return "freemarkerIndex";}
}

启动主类进行测试

2.4 freemarker模板引擎条件判断用法

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"/><title></title>
</head>
<body>
${name}
<#if sex=='0'>男<#elseif sex=='1'>女<#else>其他
</#if><#if age gte 18>已经成年啦<#else>未成年
</#if>
<#list list as user>${user}
</#list>
</body>
</html>
#比较大小 两种方法
1.用符号代替 > gt >= gte ; < lt  <=lte
2.加括号 <#if(x>y)>
@Controller
public class FreemarkerController {@RequestMapping("/freemarkerIndex")public String freemarker(Map<String,Object > result){result.put("name","blackhorse");result.put("sex","0");result.put("age",22);ArrayList<String> list=new ArrayList<>();list.add("tgxit");list.add("xiaohuihui");result.put("list",list);return "freemarkerIndex";}
}

启动主类进行测试

2.5 thymeleaf渲染web界面

引入依赖

  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

添加thymeleaf配置文件

 ##Thymeleaf模板配置thymeleaf:prefix: classpath:/templates/check-template-location: truecache: truesuffix: .htmlencoding: UTF-8mode: HTML5

编写html页面

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>UserList</title>
</head>
<body>
<table>姓名:<span th:text="${user.userName}"></span>年龄:<span th:text="${user.age}"></span>
</table></body>
</html>

启动主类测试

2.6 解决thymeleaf误报问题

代码优化

@Controller
public class MyThymeleafController {@RequestMapping("/myThymeleaf")public String myThymeleaf(HttpServletRequest request, Map<String,Object> result){result.put("user",new UserEntity("xiaohuihui",22));return "myThymeleaf";}
}

2.7 thymeleaf循环和if判断写法

@Controller
public class MyThymeleafController {@RequestMapping("/myThymeleaf")public String myThymeleaf(HttpServletRequest request, Map<String,Object> result){ArrayList<UserEntity> userEntities = new ArrayList<>();userEntities.add(new UserEntity("xiaoheihei1",23));userEntities.add(new UserEntity("xiaoheihei2",24));userEntities.add(new UserEntity("xiaoheihei3",25));result.put("userList",userEntities);return "myThymeleaf";}
}

编写html代码

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>UserList</title>
</head>
<body>
<table>//遍历userList<ul th:each="user:${userList}"><li th:text="${user.userName}"></li><li th:text="${user.age}"></li></ul>
</table></body>
</html>

启动主类测试

对年龄进行判断,代码

    <span th:if="${user.age>17}">已经成年啦</span><span th:if="${user.age<18}">未成年</span>

运行结果

详细内容可以参照thymeleaf官网

三、整合数据库访问层

1.整合JDBC

对于数据库访问层,SpringBoot底层都是采用Spring Data的方式进行统一处理
创建表

CREATE TABLE 'user'(
'id' int(11) NOT NULL AUTO_INCREMENT,
'name'varchar(32)NOT NULL COMMENT '用户名称',
'age' int(11) DEFAULT NULL,
PRIMARY KEY ('id')
)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

1.引入依赖

  <!--jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>

2.配置数据库连接
application.yml新增配置

  datasource:url: jdbc:mysql://localhost:3306/jdbcusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driver

然后测试

@SpringBootTest
class SpringbootDataApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() {System.out.println(dataSource.getClass());//输出数据源:class com.zaxxer.hikari.HikariDataSource}}

使用JDBCTemplate
新建一个JDBCController.java,用jdbcTemplate实现增删查改

@RestController//return的不在是跳转作用,而是返回字符串public class JDBCController {@AutowiredJdbcTemplate jdbcTemplate;​//查询数据库的所有信息//没有实体类 获取数据库中的东西@GetMapping("/courseList")public List<Map<String,Object>> userList(){String sql = "select * from course";List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);return maps;//返回数据库表中所有信息}​@GetMapping("/addCourse")public  String addCourse(){String sql = "insert into test.course(c_id,c_name,t_id) values(5,'生物','05')";int i = jdbcTemplate.update(sql);return i+"";}​​@GetMapping("/updateCourse/{c_id}")public String updateCourse(@PathVariable("c_id") int c_id){String sql = "update test.course set c_name = ?,t_id = ? where c_id = " + c_id;​//封装Object[] objects = new Object[2];objects[0] =  "地理";objects[1] =  "01";jdbcTemplate.update(sql,objects);return "ok!";}​@GetMapping("/deleteCourse/{c_id}")public String deleteCourse(@PathVariable("c_id") int c_id){​String sql = "delete from test.course where c_id = ?";jdbcTemplate.update(sql,c_id);return "deleteOk";​}​}

2.Druid数据源

①导入依赖

 <!--Druid数据源--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency>

appilication.yml

spring:datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#指定数据源:Druid​#Spring Boot 默认是不注入这些属性值的,需要自己绑定#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true​#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入#如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

导入log4j依赖

<!--log4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>

②创建DruidConfig.java

@Configurationpublic class DruidConfig {​//将其余application.yaml文件绑定:datasource@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource druidSource(){return new DruidDataSource();}​//后台监控功能,相当于web.xml ==> ∵springboot内置了servlet容器,所有没有web.xml 替代方法是:ServletRegistrationBean@Beanpublic ServletRegistrationBean statViewServlet(){//进入后台监控页面ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");​HashMap<String,String> initParameters = new HashMap<>();​​//添加配置,设置账号密码initParameters.put("loginUsername","admin");//登录key:loginUsername :固定写法,不能改变initParameters.put("loginPassword","123");​//允许谁可以访问initParameters.put("allow","localhost");//后面的“”如果为空,所有人就都可以访问​//禁止谁能访问initParameters.put("kalen","192.168.0.125");​​//后台需要登录,账号密码配置bean.setInitParameters(initParameters);//初始化参数 (Map参数)​return bean;}​//filter@Beanpublic FilterRegistrationBean webStatFilter(){FilterRegistrationBean bean = new FilterRegistrationBean();​bean.setFilter(new WebStatFilter());//设置过滤器HashMap<String,String> initParameters = new HashMap<>();​initParameters.put("exclusions","*.js,*.css,/druid/*");//这些路径下的不进行统计​bean.setInitParameters(initParameters);​return bean;}}

访问:http://localhost:8080/druid/login.html

3.整合Mybatis框架查询

引入依赖

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency>

在application.properties配置文件中配置数据库连接信息

  spring.datasource.username=rootspring.datasource.password=123456spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8spring.datasource.driver-class-name=com.mysql.jdbc.Driver

1.pojo类
user.java:

  @Data@AllArgsConstructor@NoArgsConstructorpublic class user {private Integer id;private String name;private String pwd;}

2.mapper(Dao层)

@Mapper //表示这是一个MyBatis的Mapper类//或者在启动类Application上加上@MapperScan("com.ckl.mapper") :扫描路径下的文件
@Repository //dao层
public interface UserMapper {​List<user> queryUserList();​user queryUserBuId(int id);​int addUser(user u);​int updateUser(user u);​int deleteuser(int id);}

3.在resource目录下新建mybatis/mapper目录
然后创建UserMapper.xml(编写sql)

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.ckl.mapper.UserMapper"><select id="queryUserList" resultType="user">select * from test.user;</select><select id="queryUserById" resultType="user">select * from test.user where id = #{id};</select>​<insert id="addUser" parameterType="user">insert into test.user(id,name,pwd) values (#{id},#{name},#{pwd});</insert><update id="updateUser" parameterType="user">update test.user set name=#{name},pwd=#{pwd} where  id=#{id};</update>​<delete id="deleteuser" parameterType="int">delete from test.user where  id=#{id};</delete></mapper>

然后在application.properties中整合mybatis:
这样就可以将xm与dao联系起来

#整合mybatis
mybatis.type-aliases-package=com.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

然后创建UserController.java,实现具体业务

@RestController
public class UserController {​@Autowiredprivate UserMapper userMapper;​@GetMapping("/user/queryUserList")public List<user> queryUserList(){List<user> users = userMapper.queryUserList();return users;}...}

4.整合redis插入、查询、修改、删除操作

配置连接信息

spring:redis:host: 127.0.0.1 port: 6379password: jedis:pool:max-active: 8max-wait: -1max-idle: 500min-idle: 0lettuce:shutdown-timeout: 0

在pom.xml文件中添加相关依赖

        <!--连接池--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--json格式转换工具--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version></dependency>

编写测试类

@RestController
@RequestMapping("/api/redis")
public class RedisController {@Autowiredprivate StringRedisTemplate redisTemplate;/*** 向redis数据库插入一条数据* @param req key:value* @return*/@PostMapping("/add")public String add(@RequestBody JSONObject req){String key=req.getString("key");String value=req.getString("value");try {redisTemplate.opsForValue().set(key,value);return "add success";} catch (Exception e) {return e.getMessage();}}@PostMapping("/find")public String find(@RequestBody JSONObject req){String key=req.getString("key");try {String value = redisTemplate.opsForValue().get(key);return "find key!value:"+value;} catch (Exception e) {return e.getMessage();}}@PostMapping("/change")public String change(@RequestBody JSONObject req){String key = req.getString("key");String value = req.getString("value");try {redisTemplate.opsForValue().set(key,value);return "change success";} catch (Exception e) {return e.getMessage();}}@PostMapping("/del")public String delete(@RequestBody JSONObject req){String key = req.getString("key");try {redisTemplate.delete(key);return "delete success";} catch (Exception e) {return e.getMessage();}}
}

使用ApiPost进行测试,向redis数据库添加key和value

请求方法:POST
请求参数: {"key":"孙悟空","value":"花果山"}
请求路径:http://localhost:8080/api/redis/add
请求结果:如图


从redis数据库查询key的value

请求方法:POST
请求参数: {"key":"孙悟空",}
请求路径:http://localhost:8080/api/redis/find
请求结果:如图


从redis数据库修改key的value

请求方法:POST
请求参数:{"key":"孙悟空","value":"水帘洞"}
请求路径:http://localhost:8080/api/redis/change
请求结果:如图


从redis数据库删除key和value

请求方法:POST
请求参数:{"key":"孙悟空"}
请求路径:http://localhost:8080/api/redis/del
请求结果:如图

四、整合Swagger接口文档

4.1 引入依赖

<!-- springfox-swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><!-- springfox-swagger-ui --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>

4.2 SwaggerConfig配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {// swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()// 为当前包路径.apis(RequestHandlerSelectors.basePackage("com.cy.springboot.controller")).paths(PathSelectors.any()).build();}// 构建 api文档的详细信息函数,注意这里的注解引用的是哪个private ApiInfo apiInfo() {return new ApiInfoBuilder()// 页面标题.title("Spring Boot 测试使用 Swagger2 构建RESTful API")// 创建人信息.contact(new Contact("Tao", "https://github.com/", "123456789@qq.com"))// 版本号.version("1.0")// 描述.description("API 描述").build();}
}

五、整合热部署框架

5.1 整合devtools工具

(1)idea设置 中勾选" Build project automatically"

(2)组合键:“Ctrl+shift+alt+/”,选择"Register",选中"compiler.automake.allow.when.app.running"

5.2 整合Lombok简化代码

普通构建实体类,需要手动创建无参构造方法和有参构造方法,Get和Set方法,以及toString方法,代码十分繁琐。

package com.example.springbootlearn.entity;import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.logging.Logger;/*** @Description:* @Author: at* @Date: 2021/8/5 17:40*/
@Data
@Slf4j
public class UserEntity {//  private static Logger log=Logger.getLogger(String.valueOf(UserEntity.class));private Integer id;private String name;private Integer age;public UserEntity(){}public UserEntity(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}//    public Integer getId() {//        return id;
//    }
//
//    public void setId(Integer id) {//        this.id = id;
//    }
//
//    public String getName() {//        return name;
//    }
//
//    public void setName(String name) {//        this.name = name;
//    }
//
//    public Integer getAge() {//        return age;
//    }
//
//    public void setAge(Integer age) {//        this.age = age;
//    }
//
//    @Override
//    public String toString() {//        return "UserEntity{" +
//                "id=" + id +
//                ", name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }public static void main(String[] args) {UserEntity userEntity=new UserEntity();userEntity.setName("张三");String username= userEntity.getName();System.out.println("username"+username);log.info("username"+username);}
}

六、整合读取配置文件

6.1 使用@value注解读取配置文件

1.在SpringBoot整合配置文件中,分成两大类:
application.properties
application.yml
或者是
bootstrap.properties
bootstrap.yml
相对于来说yml文件格式写法更加精简,减少配置文件的冗余性。

2.加载顺序
bootstrap.yml先加载,application.yml后加载。
bootstarp.yml用于应用程序上下文的引导阶段。
bootstrap.yml由父SpringApplicationContext加载。

3.区别
bootstrap.yml(bootstrap.properties)用来在程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
bootstrap.yml 先于 application.yml 加载

后期开发中yml文件格式最常用

itkt:name: 腾讯ITage: 22

编写测试类

@RestController
public class MyIndexService {@Value("${itkt.name}")private String name;@Value("${itkt.age}")private String age;@RequestMapping("/getProp")public String getProp(){return name+"--"+age;}
}

访问http://localhost:8080/getProp,读取到application.yml中的配置

6.2 properties转换yml格式

yml、properties自动转换

6.3 @ConfigurationProperties

引入依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

ITKTEntity

@Component
@ConfigurationProperties(prefix = "itkt")
public class ITKTEntity {private String name;private String age;private String address;
}

MyIndexService

@RestController
public class MyIndexService {@Value("${itkt.name}")private String name;@Value("${itkt.age}")private String age;@Autowiredprivate ITKTEntity itktEntity;/*** @Description: 使用@Value注解* @Author: At* @Date: 2021/8/5 21:19**/@RequestMapping("/getProp")public String getProp(){return name+"--"+age;}/*** @Description: @ConfigurationProperties* @Author: At* @Date: 2021/8/5 21:19**/@RequestMapping("/getNameAndAgeAddress")public String getNameAndAgeAddress(){return itktEntity.toString();}
}

6.4 整合多环境下不同配置文件

application-dev.yml:开发环境
application-test.yml:测试环境
application-prd.yml:生产环境
SpringBoot默认读取配置文件名称:application

spring:profiles:active: dev #指定环境

6.5 修改端口号和上下文路径

server:port: 8081 #端口号servlet:context-path: /itkt #指定访问路径

访问项目

七、整合日志框架

7.1 logback配置日志级别

maven依赖

         <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

Logback配置

<configuration><!--本文主要输出日志为控制台日志,系统日志,sqL日志,异常日志--><!-- ‰m输出的信息,郑p日志级别,线程名,%d日期,%c类的全名--><!--控制台--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d %p(%file: %line\)- %m%n</pattern><charset>UTF-8</ charset></encoder></appender><!--系统info级别日志--><!--<File>日志目录,没有会自动创建--><!--<roLLingPolicy>日志策略,每天简历一个日志文件,或者当天日志文件超过64MB时--><!--encoder日志编码及输出格式--><appender name="fileLog"class="ch.qos.logback.core.rolling.RollingFileAppender"><File>log/file/fileLog.1og</File><rollingPolicy class="ch.qos.logback.core.rolling. TimeBasedRollingPolicy"><fileNamePattern>log/file/fileLog.log.%d.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!--or whenever the file size reaches 64 MB --><maxFilesize>64MB</maxFilesize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--><encoder><!--`来设匿日志的输入格式--><pattern>%d %p (%file: %line1)- %m%n</pattern><charset>UTF-8</charset><!--此处设置字符集--></encoder></appender><!--sql日志--><appender name="sq1File" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>1og/sql/sqlFi1le.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/sql/sq1File.log.%d.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFN"><!--or whenever the file size reaches 64 MB --><maxFileSize>64 MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!--对记录事件进行格式化。负贲两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--><encoder><!--`来设匿日志的输入格式--><pattern>%d %p (%file: %line1)- %m%n</pattern><charset>UTF-8</charset><!--此处设置字符集--></encoder></appender><!--error日志--><appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>1og/error/errorFi1le.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/error/errorFile.%d.log.%i</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFN"><!--or whenever the file size reaches 64 MB --><maxFileSize>64 MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!--对记录事件进行格式化。负贲两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--><encoder><!--`来设匿日志的输入格式--><pattern>%d %p (%file: %line1)- %m%n</pattern><charset>UTF-8</charset><!--此处设置字符集--></encoder></appender><root level="INFO"><appender-ref ref="fileLog"/><appender-ref ref="console"/><appender-ref ref="errorFile"/></root><logger name="com.dolpin.mapper" level="DEBUG" additivity="false"><appender-ref ref="console"/><appender-ref ref="sqlFile"/></logger>
</configuration>

整合logback配置

package com.example.springbootlearn.service;import com.example.springbootlearn.entity.ITKTEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Description:* @Author: at* @Date: 2021/8/5 20:58*/
@RestController
@Slf4j
public class MyIndexService {@RequestMapping("/getLog")public String getLog(String name,int age){log.info("name:{},age:{}",name,age);log.debug("");try{}catch (Exception e){log.error("");}return name;}
}

7.2 整合log4j2日志

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--排除默认spring-boot-starter-logging启动器--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="300"><!--先定义所有的appender--><appenders><!--这个输出控制台的配置--><console name="Console" target="SYSTEM_OUT"><!--输出日志的格式--><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/></console><!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用--><File name="log" fileName="exam/exam.log" append="false"><PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/></File><!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFileInfo" fileName="exam/logs/info.log"filePattern="exam/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log"><Filters><!--如果是warn级别以上的拒绝--><ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/><!--只输出info级别的--><ThresholdFilter level="info" onMatch="NEUTRAL" onMismatch="DENY"/></Filters><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><Policies><TimeBasedTriggeringPolicy/><SizeBasedTriggeringPolicy size="100 MB"/></Policies></RollingFile><RollingFile name="RollingFileWarn" fileName="exam/logs/warn.log"filePattern="exam/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log"><Filters><!--如果是error级别以上的拒绝--><ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/><!--只输出warn级别的--><ThresholdFilter level="warn" onMatch="NEUTRAL" onMismatch="DENY"/></Filters><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><Policies><TimeBasedTriggeringPolicy/><SizeBasedTriggeringPolicy size="100 MB"/></Policies><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 --><DefaultRolloverStrategy max="20"/></RollingFile><RollingFile name="RollingFileError" fileName="exam/logs/error.log"filePattern="exam/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log"><ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><Policies><TimeBasedTriggeringPolicy/><SizeBasedTriggeringPolicy size="100 MB"/></Policies></RollingFile></appenders><!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--><loggers><root level="all"><appender-ref ref="Console"/><appender-ref ref="RollingFileInfo"/><appender-ref ref="RollingFileWarn"/><appender-ref ref="RollingFileError"/></root></loggers>
</configuration>

八、整合定时任务

8.1 使用创建定时任务

在Spring Boot的主类中加入@EnableScheduling 注解,启用定时任务的配置
一个方法上设置了 fixedDelay=51000,那么当该方法某一次执行结束后,开始计算时间,当时间达到5秒,就开始再次执行该方法。
当方法上设置了 fiexdRate=5
1000,该执行该方法所花的时间是2秒,那么3秒后就会再次执行该方法。
第一种

@Configuration
@EnableScheduling
public class Schedule_1 {@Scheduled(cron = "0/5 * * * * ?")public void ScheduledM1() {System.err.println("【静态】执行定时任务:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒")));}
}

第二种

@Configuration
@EnableScheduling
public class Schedule_2 implements SchedulingConfigurer {// 匿名内部类形式@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.addTriggerTask(new Runnable() {@Overridepublic void run() {System.err.println("【动态】执行定时任务:" + LocalTime.now().toString() + "\n");}}, new Trigger() {@Overridepublic Date nextExecutionTime(TriggerContext triggerContext) {String cron = "0/5 * * * * ?";System.out.println("cron表达式为:" + cron);// 此处的cron可以从数据库中获取   重点return new CronTrigger(cron).nextExecutionTime(triggerContext);}});}// lambda表达式形式
//    @Override
//    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {//        taskRegistrar.addTriggerTask(() -> {//            System.err.println("【动态】执行定时任务:" + LocalTime.now().toString() + "\n");
//        }, (triggerContext) -> {//            String cron = "0/5 * * * * ?";
//            System.out.println("cron表达式为:" + cron);
//            // 此处的cron可以从数据库中获取   重点
//            return new CronTrigger(cron).nextExecutionTime(triggerContext);
//        });
//    }
}

第三种

@Configuration
@EnableScheduling
@EnableAsync
public class Schedule_3 {//多个定时器同步执行
//      @Scheduled(cron = "0/1 * * * * ?")
//    public void s1() throws InterruptedException {//        Thread.sleep(5000);
//        System.out.println("【同步1】执行定时任务:" + LocalTime.now().toString());
//    }
//
//    @Scheduled(cron = "0/1 * * * * ?")
//    public void s2() {//        System.err.println("【同步2】执行定时任务:" + LocalTime.now().toString());
//    }//多个定时器异步执行@Async@Scheduled(cron = "0/1 * * * * ?")public void s1() throws InterruptedException {Thread.sleep(5000);System.out.println("【异步1】执行定时任务:" + LocalTime.now().toString());}@Async@Scheduled(cron = "0/1 * * * * ?")public void s2() {System.err.println("【异步2】执行定时任务:" + LocalTime.now().toString());}
}

8.2 定时任务

@Component
@Slf4j
public class scheduledTasks {/***每隔2s时间执行到taskService*/@Scheduled(cron ="1/2****?")public void taskService() {log.info("<<定时任务执行>>"+ system.currentTimeMillis());}
}

九、整合多线程异步

9.1 使用@Async实现异步调用

启动类加上@EnableAsync ,需要执行异步方法上加入 @Async,@Async实际就是多线程封装的。

异步执行方法可能会非常消耗CPU资源,所以大项目建议使用MQ异步实现

@RestController
@Slf4j
public class MemberService(){@RequestMapping( "/addMember")public string addMember() {//1.数据库插入数据log.info(">01<");//2.发送短信new Thread(new Runnable(){@Overridepublic void run(){sms();}}).start();log.info(">04<");return“用户注册成功";public string sms() {log.info(">02<");try {log.info(">正在发送短信..<");Thread.sleep(millis: 300e);}catch (Exception e) {}log.info(">03<");return "短信发送完成!";}
}
@SpringBootApplication
@EnableScheduling
public c1ass App (){public static void main(String[] args){ SpringApplication.run(App.class); }
}

9.2 @Async失效问题

注意:如果异步注解写当前自己类,有可能aop会失效,无法拦截注解,最终导致异步失效,需要经过代理类调用接口;
所以需要将异步的代码单独抽取成一个类调用接口。

编写MemberServiceAsync类

@Component
@S1f4j
public class MemberServiceAsync {@Asyncpublic String sms()log.info(">02<");try {log.info(">正在发送短信..<");Thread.sleep( millis: 3000);} catch (Exception e) {}log.info(">03<");return "短信发送完成!";}
}

编写MemberService类

@RestController
@Slf4j
public class MemberService(){@Autowiredprivate MemberServiceAsync memberServiceAsync;@RequestMapping("/addMember")public string addMember() {//1.数据库插入数据log.info(">01<");memberServiceAsync.sms();log.info(">04<");return "用户注册成功";}
}

9.3 @Async整合线程池

config包下新建ThreadPoolconfig 类

@Configuration
@EnableAsync
public class ThreadPoolconfig {/***每砂需要多少个线程处理?*tasks/(1/taskcost)*/private int corePoo1Size = 3;/***线程池维护线程的最大数量*(max (tasks)- queuecapacity)/(1/taskcost)*/private int maxPoolsize = 3;/***缓存队列*( coresizePooL/taskcost) *responsetime*/private int queuecapacity = 10;/***允许的空闲时间*默认为6日*/private int keepAlive = 100;@Beanpublic TaskExecutor taskExcutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//设置核心线程数executor.setCorePoolsize( corePoolSize);//设置最大线程数executor.setMaxPoolsize(maxPoo1size);//设置队列容量executor.setQueuecapacity(queuecapacity) ;//设置允许的空闲时间(秒)//executor.setKeepAliveseconds( keepALive);//设置默认线程名称executor.setThreadNamePrefix( "thread-" );//设置拒绝策略rejection-policy:当pool己经达到max size的时候,如何处理新任务//CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行executor.setRejectedExecutionHandler(new ThreadPoo1Executor.callerRunsPolicy());//等待所有任务结束后再关闭线程池executor.setWaitForTasksToCompleteonShutdown(true);return executor;}
}

编写MemberServiceAsync

@Component
@S1f4j
public class MemberServiceAsync(){@Async("taskExecutor") //指定线程池名称public string sms(){log.info(">02<");try {log.info(">正在发送短信..<");Thread.sLeep(millis: 3000);}catch(Exception e) {}log.info(">03<");return "短信发送完成!";}
/**
*′线程池*/
}

十、SpringBoot文件上传

10.1 文件上传

@ResponseBody
@RequestMapping(value = "uploadFile")public String upload(MultipartFile file) throws IOException {//获取文件原始名和后缀名String originalFilename = file.getOriginalFilename();//获取文件原始名字String fileOrgName = originalFilename.substring(0, originalFilename.lastIndexOf("."));//获取文件后缀String extension = "." + FilenameUtils.getExtension(originalFilename);//生成新的文件名字String newFileName = fileOrgName + UUID.randomUUID().toString().replace("-", "") + extension;//指定实际文件目录String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";//使用日期文件目录String dateDirPath = realPath + "/"+new SimpleDateFormat("yyyy-MM-dd").format(new Date());System.out.println(dateDirPath);File dateFile = new File(dateDirPath);if (!dateFile.exists()) {dateFile.mkdirs();}//文件上传file.transferTo(new File(dateDirPath, newFileName));return "文件上传成功";}

10.1 文件下载

@ResponseBody
@RequestMapping(value = "downloadFile")public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files/2022-09-07";FileInputStream fileInputStream = new FileInputStream(new File(realPath, fileName));//附件下载方式response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));ServletOutputStream outputStream = response.getOutputStream();IOUtils.copy(fileInputStream, outputStream);IOUtils.closeQuietly(fileInputStream);IOUtils.closeQuietly(outputStream);return "文件下载成功";}

十一、项目打包部署

11.1 整合全局捕获异常

@ExceptionHandler表示拦截异常
@ControllerAdvice是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类@ControllerAdvice可以指定扫描范围
@ControllerAdvice约定了几种可行的返回值,如果是直接返回model 类的话,需要使用
@ResponseBody进行json转换

  • 返回String,表示跳到某个view
  • 返回modelAndView
  • 返回 model +@ResponseBody

捕获运行时异常,返回json格式

@ControllerAdvice
public c1ass ExceptionHandler(){@ExceptionHandler(RuntimeException.class)@ResponseBodypublic Map<Object,Object> exceptionHandler() {HashMap<Object,Object> result = new HashMap<>();result.put("code",500);result.put("msg","系统错误");return result;}
}

返回页面,去掉@ResponseBody注解

@ControllerAdvice
public c1ass ExceptionHandler(){@ExceptionHandler(RuntimeException.class)//@ResponseBodypublic String exceptionHandler() {return null;
}

11.2 打包运行发布

mvn package
java - jar包名

如果报错没有主清单,在 pom文件中新增

    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions><configuration><mainClass>com.example.springbootlearn.SpringbootLearnApplication</mainClass><excludes><exclude><groupId>junit</groupId><artifactId>junit</artifactId></exclude><exclude><groupId>org.springframework. boot</groupId><artifactId>spring-boot-starter-test</artifactId></exclude></excludes></configuration></plugin></plugins></build>

在项目文件夹中,打开cmd命令窗口

mvn clean package

SpringBoot整合笔记相关推荐

  1. SpringBoot学习笔记(16)----SpringBoot整合Swagger2

    Swagger 是一个规范和完整的框架,用于生成,描述,调用和可视化RESTful风格的web服务 http://swagger.io Springfox的前身是swagger-springmvc,是 ...

  2. 2.6 springBoot学习笔记(2.6)——- 整合mybatisPlus

    更多文章 更多系列文章在个人网站 springBoot学习系列笔记文章 springBoot学习笔记(1)-- 搭建springBoot项目 文章目录 更多文章 springBoot学习系列笔记文章 ...

  3. SpringBoot整合第三方技术学习笔记(自用)

    SpringBoot整合第三方技术学习笔记 搬运黑马视频配套笔记 KF-4.数据层解决方案 KF-4-1.SQL 回忆一下之前做SSMP整合的时候数据层解决方案涉及到了哪些技术?MySQL数据库与My ...

  4. Redis学习笔记(二)SpringBoot整合

    Redis学习笔记(二) SpringBoot整合 测试 导入依赖 查看底层 配置连接 测试连接 自定义`RedisTemplate` 在开发中,一般都是以json来传输对象: 所以实际开发中所有对象 ...

  5. SpringBoot学习笔记(三)用户登录、授权、认真、数据库整合框架

    SpringBoot整合JDBC 配置 application.yaml中配置 spring:datasource:username: 用户名password: 密码url: jdbc:mysql:/ ...

  6. 2019.12.24笔记——SpringBoot整合Elasticsearch及其使用

    目录 Elasticsearch与springboot整合的方式 原生客户端 REST Jest Spring Data Spring Data的配置 Spring Data的使用 插入或修改数据 删 ...

  7. Activiti学习笔记:Activiti和Spring整合、Activiti和SpringBoot整合之Gradle版

    环境 activiti:7+ Java:11 本机环境:window MySQL:5.7 gradlew:6+ Activiti和Spring整合 大体流程: 先创建项目,并导入依赖 添加activi ...

  8. SpringBoot学习笔记(4)----SpringBoot中freemarker、thymeleaf的使用

    1. freemarker引擎的使用 如果你使用的是idea或者eclipse中安装了sts插件,那么在新建项目时就可以直接指定试图模板 如图: 勾选freeMarker,此时springboot项目 ...

  9. (一)SpringBoot 整合 MyBatis

    一.工具 IDE:idea.DB:mysql 二.创建SpringBoot工程 在Idea中使用SpringInitializr模板创建SpringBoot工程,依赖选择如下: 这里也可以不选JDBC ...

最新文章

  1. 生动的解释下什么是 MySQL 的“回表”?
  2. 项目部署不到tomcat中的原因和解决方法
  3. 我们不要框计算 我们要更好的搜索体验
  4. 26、jdbc操作数据库(3)
  5. VAD实现(一) 读取语音数据
  6. 基于jenkins的自动化部署实现
  7. django判断ajax,Django ajax 检测用户名是否已
  8. 卡方分布的定义与概率密度的计算
  9. Xenko C#开源游戏引擎
  10. MFC功能扩展控件BCGSuite for MFC入门指南
  11. 禁用计算机声卡设备,电脑声音被禁用了怎么办
  12. sql概念模型和逻辑模型
  13. 思科模拟器配置-生成树协议与链路聚合负载均衡
  14. 微信玩这个 存款惊人_英语的8个惊人新趋势
  15. 使用R语言画火山图详细步骤
  16. electron实现屏幕录制
  17. 关于运筹学三方库的编译和使用 ortools
  18. 攻读学位研究计划计算机专业,拟攻读博士学位的科学研究计划书模板
  19. 问题定义工具和三种问题定义思维模式
  20. C#实现图书管理系统(课程设计)——第二步、登陆界面

热门文章

  1. 网络爬虫课程介绍及网络爬虫是什么
  2. 计算机管理任务计划程序损坏,win7旗舰版的任务计划程序崩溃了,怎么处理?
  3. 和iPhoto道别 iOS 10/OS X将有大调整
  4. 设置python环境变量的三种方法(pycharm)
  5. 终于想起了Matrix的登录密码了
  6. 使用selectKey报错
  7. OpenStack,开源云十年
  8. 眼底病php 是什么病,什么是眼底病 五种常见眼底病详述
  9. [Puppeteer]Puppeteer实现自动网赚?
  10. “山河无恙,网络清朗”之金刚钻