Skip to content

第二章 Spring 基础(一) v1.0 ​

第一部分 分层解耦 ​

一、IOC与DI ​

1.控制反转(Inversion Of Control,简称IOC) ​

对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

将对象交给IOC容器管理,需要在对应的类上加上如下注解之一:

将Service层与Dao层的实现类交由IOC容器管理:

java
@Component  //将实现类交由IOC容器管理
public class MyDao {
    //...
}

2.依赖注入(Dependency Injection,简称DI) ​

容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

为Controller及Service注入运行时依赖的对象:

java
@Component  //将实现类交由IOC容器管理
public class MyService {
    @Autowired  //(默认按照类型)进行依赖注入
    private MyDao MyDao;
    //...
}
java
public class SimpleMovieLister {
    private MovieFinder movieFinder;
    
	@Autowired  //可以省略
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
java
public class SimpleMovieLister {
    private final MovieFinder movieFinder;
    
    @Autowired  //可以省略
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}

解决依赖注入的三种方案:

java
@Primary
@Service
public class ServiceA implements Service {}
java
@RestController
public class Controller {
    @Autowired
    @Qualifier("serviceA")
    private Service service;
}
java
@RestController
public class EmpController {
    @Resource(name = "serviceA")
    private Service service;
}

@Resource与@Autowired区别

  1. @Autowired是spring框架提供的注解,而@Resource是JDK提供的注解。

  2. @Autowired默认按照类型注入,而@Resource默认按照名称注入。

3.Bean对象 ​

IOC容器中创建、管理的对象,称之为bean,名称默认为类名首字母小写,如myClass

Bean组件扫描配置:使用@ComponentScan配置需要扫描的组件

实际上已经包含在启动类声明注解@SpringBootApplication中,默认扫描范围是启动类所在包及其子包

二、XML方式配置IOC ​

早期的Spring项目也可以通过applicationContext.xml声明Bean。name与id使用基本一致,但name允许使用一些特殊字符。

Spring XML配置

Spring XML Bean配置

xml
<beans>
  <bean id="..." class="全类名"></bean>
  <bean name="..." class="全类名"></bean>
</beans>

BeanFactory与ApplicationContext的关系和使用方式仍保留在旧版 IOC 笔记中的图示中。

BeanFactory与ApplicationContext

第二部分 配置 ​

一、参数配置化 ​

使用Value注解:@Value("${key}") //key为application.properties配置文件中内容

java
//方式1:注入普通属性(不能为静态变量)
@Value("${myKey}")
private String parm;

//方式2:在构造函数中使用@Value注解
static String parm;
public MyClass(@Value("${myKey}") String parm) {
    MyClass.parm = parm;
}

//方式3:在setter函数中使用@Value注解
static String parm;
@Value("${myKey}")
public void setParm(String parm){
    parm = parm;
}

二、不同格式的配置文件 ​

1.application.properties ​

优先级较高,低于命令行参数和Java系统属性

properties
server.port=8080
server.address=127.0.0.1
server.user-name=user

2.application.yml与application.yaml ​

优先级最低

yaml
server:
  port: 8080
  address: 127.0.0.1
	user-name: user
#数组/List/Set
mylist:
	- element1
  - element2

基本语法:

  1. 大小写敏感
  2. 数值前边必须有空格,作为分隔符
  3. 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
  4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  5. #表示注释,从这个字符一直到行尾, 都会被解析器忽略

三、使用实体类注入配置 ​

java
@Data
@Component
@ConfigurationProperties(prefix="server")  //prefix为前缀
public class MyProperties {
    private String port;
    private String address;
    private String userName;
}

//使用配置
@Autowired
private MyProperties myProperties;
myProperties.getPort();
//......
xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

注意要点:

application配置文件中命名要与注入实体类属性名一致或将驼峰命名转化为使用**-**分隔风格命名

四、服务器运行SpringBoot项目 ​

1.进行打包 ​

运行打包命令:mvn package

2.在服务器运行 ​

java
java -jar <...>.jar --server.port=<端口号>

3.Java系统属性配置 ​

优先级次高,低于命令行参数,高于配置文件

格式:-Dxxx.xxx=xxx,示例:-Dserver.port=8080

4.命令行参数配置 ​

优先级最高

格式:--xxx.xxx=xxx,示例:--server.port=8080

第三部分 请求处理 ​

一、控制器类 ​

1.简介 ​

Spring MVC框架中,控制器类主要职责为处理HTTP请求

2.实现 ​

java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;  //GetMapping等同目录

@Controller
@RequestMapping("/home/")  //类级别请求映射注解
public class <类名> {
    @GetMapping("/")  //修饰方法的请求映射注解
    public ... {}  //请求处理方法
}

3.请求映射注解 ​

注意:后面五种注解为Spring 4.3引入,在之前可以通过方法级别的@RequestMapping注解替代

java
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping(value="/", method=RequestMethod.GET)  //等价于@GetMapping("/"),其他注解类似

二、简单参数请求 ​

  1. 原始方式

在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取。

java
@RequestMapping("test")
public StatusResponse test(HttpServletRequest request){
    System.out.println(request.getParameter("name"));
    return new StatusResponse(1,"true");
}
  1. SpringBoot方式

只需要前端请求参数名与形参变量名相同,定义形参即可接收参数。

java
@RequestMapping("test")
public StatusResponse test(String name){
    System.out.println(name);
    return new StatusResponse(1,"true");
}

当方法形参名称与请求参数名不匹配,可以使用@RequestParam完成映射

@RequestParam原型:@RequestParam(name="参数名", required=true)​

@RequestParam中required属性默认为true,代表请求参数必须传递,若参数可选可以改为false

java
@RequestMapping("test")
public StatusResponse test(@RequestParam(name="name")String name){
    System.out.println(name);
    return new StatusResponse(1,"true");
}

三、实体参数 ​

实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可

java
public class User {
    private String name;  //访问参数:name
    private UserData data;
}

public class UserData {
    private Integer age;  //访问参数:data.age
    private String address;  //访问参数:data.address
}

四、数组集合参数 ​

请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数

  1. 声明一个数组,参数名与请求参数名保持一致
  2. 使用集合类,使用@RequestParam绑定参数关系,如:@RequestParam List<String> name

五、日期参数 ​

使用@DataTimeFormat进行转换,并使用日期类型,如LocalDateTime接收即可

原型:@DataTimeFormat(pattern="...")

使用示例:@DataTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime time

六、JSON请求 ​

JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用@RequestBody标识

java
public class User {
    private String name;  
    private UserData data;
}

public class UserData {
    private Integer age;  
    private String address; 
}
json
{
  "name":"Tom",
  "data":{
    "age":18,
    "address":"Chang Sha"
  }
}

七、路径参数 ​

通过URL直接传递参数,Mapping中使用{...}来标识该路径参数,需要使用@PathVariable获取路径参数

java
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id){
    System.out.println(id); 
    return "OK , get id " + id;
}