Featured image of post Spring Boot 初遇

Spring Boot 初遇

Spring Boot 开始学习与基本使用

简介

什么是 Spring Boot

  1. 简化 Spring 应用开发的框架
  2. 整个 Spring 技术栈的一个大整合
  3. J2EE 的一站式解决方案

Spring Boot 的优点

  1. 快速创建独立运行的 Spring 项目及主流框架集成
  2. 使用嵌入式 Servlet 容器,无序打包成 WAR 文件
  3. starters 自动依赖与版本控制
  4. 大量自动配置,也可修改默认值
  5. 无须配置 XML
  6. 准生成环境运行时应用监控
  7. 与云计算天然集成

微服务

微服务是一种架构风格,下面是基本特点:

  1. 一系列小服务的集成
  2. 每一个功能元素最终都是可独立替换和独立升级的元素

基础入门

项目结构

依赖管理配置文件是 pom.xml

全局配置文件是 application.properties application.yml

文件格式 utf-8,Spring 编码该文件是 ASCII,解码是 utf-8

application.yml

  1. K: V:表示一对键值对

缩进表示层级关系,同一缩进为同一层级

大小写敏感

  1. 值是字符串:

    1. 单引号:转义特殊字符
    2. 双引号:不转义特殊字符

值是对象:

1
2
3
4
5
animal: {cat: 1,dog: 2}
# 或者
animal: 
	cat: 1
	dog: 2

值是数组:

1
2
3
4
5
6
pets: [cat,dog,pig,...]
# 或者
pets:
	- cat
	- dog
	- pig

入口函数是 DemoApplication.java

测试

	test文件夹

配置文件注入

@ConfigurationProperties

全局批量注入

  • 创建需要注入的类并添加注解
1
2
3
4
5
6
7
@Component
@ConfigurationProperties(prefix = "person")
// @PropertySource(value = {"classpath:*.properties,classpath:*.yml"})
// @ImportResource(locations = "classpath:*.xml")
// @Configuration
@Validated
public class Person {}
  • 配置注入值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# application.properties 和 application.yml 都能作为配置文件,都存在优先前者(有编码问题)
person:
  chineseName: 小小
  englishName: Saly
  age: 18
  isBoss: false
  borth: 2000/01/01
  maps: { k1: v1, k2: v2 }
  lists:
    - cat
    - dog
  dog:
    name: Tom
    age: 3

@Value

单个注入

@ConfigurationProperties @Value
功能 批量注入 单个注入
松散绑定 支持 不支持
四则运算 不支持 支持
数据校验 支持 不支持
复杂类型封装 支持 不支持

@PropertySource 局部批量注入

@ImportResource 导入xml注入

@Configuration 配置类注入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Configuration  //配置类
public class AccountConfig {
    // 创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///test?characterEncoding=utf8");
        dataSource.setUsername("root");
        dataSource.setPassword("Ljt1123581321");
        return dataSource;
    }
}

配置文件占位符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# ${random.uuid} 随机64位字符
# ${random.value} 随机64位字符
# ${random.int}	随机整型
# ${random.long}	随机长整型
# ${person.chineseName}	获取配置文件的属性值
# ${person.hello:hello}	获取配置文件的属性值,如果没有这个属性,使用默认值
person:
  chineseName: 小小_${random.uuid}
  englishName: Saly_${random.value}
  age: ${random.int}
  isBoss: false
  borth: 2000/01/01
  maps: { k1: v1, k2: v2 }
  lists:
    - cat_${person.chineseName}
    - dog
  dog:
    name: Tom_${person.hello:hello}
    age: 3

profile 配置多环境

创建多个properties文件:

  1. application.properties
  2. application-dev.properties
  3. application-prod.properties

在第一个配置文件中设置:spring.profiles.active=dev | prod,将会采用第二或第三个文件

使用 yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 文档块
server: 
  port: 9001
spring: 
  profiles:
    active: dev
---
server: 
  port: 9002
spring: 
  profiles: dev
---
server: 
  port: 9003
spring: 
  profiles: prod

配置文件的默认加载路径

  1. 当前工程/config
  2. 当前工程
  3. resources/config
  4. resources
  • 优先级从上到下全部加载,同配置覆盖,不同配置互补
  • 可以通过 spring.config.location 增加新的配置文件
  • 外部 jar 优先内部,带 spring.profiles.active 优先不带

日志

日志抽象层和实现框架

抽象层 实现框架
JCL(Jakarta Commons Logging):14年停止更新、 SLF4J(Simple Logging Facade For Java)、 jboss-logging:淘汰 JUL(java.util.logging):java自带、 log4j:同步阻塞、 logback:log4j新版、 log4j2:异步非阻塞

Spring Boot使用日志

yaml 配置使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# log 日志

logging:
  level: #更改默认日志等级
    study:
      config: trace

  path: #输出log文件路径(默认spring.log)
  file: #输出log文件路径 + 文件名
  
  pattern:
    console: %d{yyyy-MM--dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n #指定控制台输出格式
    file: #指定文件中日志格式

xml 配置使用

  1. logback:

    1. logback-spring.xml
    2. logback.xml
    3. logback-spring.groovy
    4. logback.groovy
  2. log4j2:

    1. log4j2-spring.xml
    2. log4j2.xml
  3. JUL(java.util.logging):

    1. logging.properties

其中:加了spring的可被spring解析,能指定不同环境等高级功能

lombok 使用

导入依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<optional>true</optional>
	</dependency>

<!-- 如果还导入了 maven 打包插件,需排配置如下 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

导入 lombok 支持插件(VS Code),IDEA同样也需要导入

注解用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Setter					//生成 set 方法
@Getter					//生成 get 方法
@Data					//生成 get 、 set 方法
@ToString				//生成 toString 方法
@NoArgsConstructor		//生成 无参 构造器
@AllArgsConstructor		//生成 所有属性 构造器
@EqualsAndHashCode		//生成 equals 和 hashCode 方法
@Slf4j					//注入日志,log实例
public class User {
    private String name
    private Integer age;
    
    log.info("");
}

Web开发

静态资源访问

静态资源访问目录

如上图:src/main/resources 目录下的 public 目录都是静态资源文件夹

Controller 不能处理的请求交给静态资源处理器,在这个四个文件夹寻找资源

改变默认路径、访问资源加前缀

1
2
3
4
5
spring:
	mvc:
		static-path-pattern: /res/**	#改变访问资源加前缀
	recources: 
		static-locations: [classpath:/aaa/]		#改变默认路径

webjar: js资源 jar 包

1
2
3
4
5
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>

js资源 jar 包地址

导入依赖后可通过 locahost:9000/webjars/jquery/3.6.0/jquery.js 访问到

欢迎页测试

  1. 默认加载静态资源路径下的 index.html 页面,和小图标
  2. 如果配置了访问前缀,将失效

请求处理

常用参数注解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@RestController
public class ParameterController {
    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, String> getCar(  @PathVariable("id") Integer id, //获取请求路径中的变量
                                        @PathVariable("username") String username,
                                        @PathVariable Map<String, String> pv,   //获取请求路径中所有变量
                                        @RequestHeader("User-Agent") String agent,  //获取请求头中指定信息
                                        @RequestHeader Map<String, String> header,  //获取请求头全部信息
                                        @RequestParam("age") Integer age,   //获取请求指定参数
                                        @RequestParam Map<String, String> params,   //获取请求所有参数
                                        @CookieValue Cookie cookie) {   //获取请求Cookie
        Map<String, String> map = new HashMap<>();

        map.put("id", id.toString());
        map.put("username", username);
        map.put("pv", pv.toString());
        map.put("agent", agent);
        map.put("header", header.toString());
        map.put("age", age.toString());
        map.put("params", params.toString());
        map.put("cookie", cookie.toString());

        return map;
    }
    
    @PostMapping("/submit")
    public Map<String, String> postSubmint( @RequestBody String body, //获取post请求的请求体
                                            User user) {  //表单提交数据自动注入
        Map<String, String> map = new HashMap<>();

        map.put("body", body);
        map.put("user", user.toString());

        return map;
    }
}
  1. User user自动注入底层原理:是将字符串 ==> JavaBean类中属性对应的类型
  2. 自定义提交数据类型转换方法

@RequestAttribute

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Controller
public class JumpController {
    @GetMapping("/goto") 
    public String jump(HttpServletRequest request) {
        request.setAttribute("msg", "请求成功!");
        request.setAttribute("id", "111111111");

        return "forward:/success";
    }

    @ResponseBody
    @GetMapping("/success")
    public Map<String, String> success( @RequestAttribute("msg") String msg,    //获取 HttpServletRequest 设置的属性
                                        @RequestAttribute("id") String id,
                                        HttpServletRequest request) {   //和跳转前页面的 HttpServletRequest 是同一个
        Object msg1 = request.getAttribute("msg");
        Object id1 = request.getAttribute("id");

        Map<String, String> map = new HashMap<>();

        map.put("msg", msg);
        map.put("id", id);
        map.put("msg1", msg1.toString());
        map.put("id1", id1.toString());

        return map;
    }
}

@MatrixVariable

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@RestController
public class MatrixController {
    @GetMapping("/matrix/{path}")  //必须有变量路径才能获取 矩阵变量
    public Map<String, String> matrix(  @MatrixVariable(value = "pet",pathVar = "path") String pet,  //获取请求路径中 矩阵变量
                                        @MatrixVariable(value = "ages",pathVar = "path") List<String> ages,
                                        @PathVariable("path") String path) {
        Map<String, String> map = new HashMap<>();

        map.put("pet", pet);
        map.put("ages", ages.toString());
        map.put("path", path);

        return map;
    }
}
  • 默认是不生效的

  • 需要添加配置类,配置属性生效

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Configuration(proxyBeanMethods = false)
public class WebConfig {
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer(){
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                urlPathHelper.setRemoveSemicolonContent(false); //设置不移除请求路径 ; 后面的内容
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }
}

Map、Model添加到Request请求域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
	@GetMapping("/goto2") 
    public String jump2(Map<String, String> map, Model model, HttpServletRequest request, HttpServletResponse response) {
        
        map.put("hello", "hello");
        model.addAttribute("world", "world");
        request.setAttribute("message", "success!");
        Cookie cookie = new Cookie("c1", "v1");
        response.addCookie(cookie);

        return "forward:/success2";
    }

    @ResponseBody
    @GetMapping("/success2")
    public Map<String, String> success2(HttpServletRequest request) {   //和跳转前页面的 HttpServletRequest 是同一个
        Object hello = request.getAttribute("hello");
        Object world = request.getAttribute("world");
        Object message = request.getAttribute("message");

        Map<String, String> map = new HashMap<>();


        map.put("hello", hello.toString());
        map.put("world", world.toString());
        map.put("message", message.toString());

        return map;
    }

数据响应

默认响应 json 数据

  • 导入依赖
1
2
3
4
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 返回对象(解析器默认自动解析成 json)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Controller
public class ResponseController {
    @ResponseBody
    @GetMapping("/response/user")
    public User getUser() {
        User user = new User("Saly", "[email protected]");

        return user;
    }
}

设置请求参数返回 xml、json

  • 导入 xml 依赖
1
2
3
4
5
<!-- 请求返回 xml 数据依赖 -->
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
		</dependency>
  • 配置文件
1
2
3
4
spring:
  mvc:
    contentnegotiation:
      favor-parameter: true
Licensed under CC BY-NC-SA 4.0