Spring筆記1——極簡入門教程

環境準備

  • 系統:MacOS
  • 開發:IntelliJ IDEA
  • 語言:Java8
  • 其它:Mysql、Redis

腳手架代碼

Spring提供了一個創建項目腳手架的官網,在這裏可以直接定製項目的框架代碼。例如:

圖片描述

注意:在Dependencies中,添加了Web依賴。

點擊【Generate Project】,即可下載項目框架代碼。

創建工程

將框架代碼包解壓後放到工作目錄。打開IDEA,點擊【File] -> 【Open】,打開對應目錄。

啓動工程

找到com.spring.demo.demo下的DemoApplication,右鍵點擊運行後,console中即可顯示Spring啓動的信息。
圖片描述

Controller

在傳統MVC架構中,Controller負責接收Http請求並返回相應的應答,這個應答可以是一個頁面,也可以是一個JSON對象。方便起見,本教程使用RestfulAPI爲例。

添加RestController

創建一個UserController,負責響應User相關的業務請求。對於純數據的API接口,使用@RestControll進行標註,這樣每一個API接口的返回值就會被轉化爲JSON結構的數據。

package com.spring.demo.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping("/user")
    public String find() {
        return "UserA";
    }
}

重啓應用,在瀏覽器中請求http://localhost:8080/user,即可看到請求的返回內容:UserA。

路徑參數

對於帶路徑參數的請求,可以通過@PathVariable 標註來獲取參數值。如:

package com.spring.demo.demo.controller;

import org.springframework.web.bind.annotation.PathVariable;
...

@RestController
public class UserController {

    @RequestMapping("/user/{id}")
    public String find(@PathVariable int id) {
        return "用戶ID[" + id + "]";
    }
}

POST請求

對於POST請求,可以使用@PostMapping 來標註方法,接收的JSON數據需要使用@RequestBody來標註。

    ...
    @PostMapping("/user")
    public void create(@RequestBody UserCreateRequest user) {
        System.out.println(user.getName());
    }
    ...

這裏的UserCreateRequest,用來接收並轉換JSON數據。

package com.spring.demo.demo.dto;

public class UserCreateRequest {

    private String name;
    private boolean gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isGender() {
        return gender;
    }

    public void setGender(boolean gender) {
        this.gender = gender;
    }
}

在IDEA的Terminal中,使用curl來進行測試。

curl -XPOST 'http://127.0.0.1:8080/user' -H 'Content-Type: application/json' -d'{"name":"用戶A","gender":0}'

參數校驗

有時我們需要對傳入參數進行非空或有效值的校驗,這個處理應該在正式進入controller前進行。

1. 添加@Validated標註

在SpringMVC中,對輸入參數進行校驗通常使用@Validated標註。

    ...
    @PostMapping("/user")
    public void create(@RequestBody @Validated UserCreateRequest user) {
        System.out.println(user.getName());
    }
    ...

2. 添加校驗規則標註@

在對應的字段上,加上對應的校驗規則標註。

package com.spring.demo.demo.dto;

import javax.validation.constraints.NotNull;

public class UserCreateRequest {

    @NotNull
    private String name;

    private boolean gender;

    // Getters & Setters
    ...
}

添加後重啓服務,發送不含name字段的POST請求,結果如下:
圖片描述

Service

MVC框架中,Controller負責接收請求和相應,Service則負責具體的業務處理,即Model層。

Service在定義是需要使用@Service標註,SpringBoot在啓動中將會註冊該Service並在Controller通過DI來實例化並使用該Service。

一般來說,我們會創建一個Service的接口類和一個對應的實現類。

IUserService

package com.spring.demo.demo.service;

public interface IUserService {
    public String findUser(int id);
}

UserService

package com.spring.demo.demo.service;

import org.springframework.stereotype.Service;

@Service
public class UserService implements  IUserService {

    public String findUser(int id) {
        return "用戶" + id;
    }
}

在調用時,Controller會直接應用接口類,並添加@Autowired標籤。這裏的調用原理,即是Sping最著名的DI(依賴注入)和IoC(控制反轉)。

package com.spring.demo.demo.controller;

import com.spring.demo.demo.dto.UserCreateRequest;
...

@RestController
public class UserController {

    @Autowired
    IUserService userService;

    @RequestMapping("/user/{id}")
    public String find(@PathVariable int id) {
        return userService.findUser(id);
    }

    @PostMapping("/user")
    public void create(@RequestBody @Validated UserCreateRequest user) {
        System.out.println(user.getName());
    }
}

此時重啓Spring,並使用curl進行請求,可以得到結果:

$ curl -XGET 'http://127.0.0.1:8080/user/100' 
$ 用戶100

Repository

Spring本身集成了Spring Data JPA,用來作爲訪問數據庫的ORM工具,它採用了Hibernate實現。在本教程,我們將實現User的增和查的工作。

添加依賴

修改pom.xml,添加對mysql和jpa的支持。

  ...
  <dependencies>
    ...
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
  </dependencies>

服務配置

修改/resources/application.properties,添加相關的設置。

...
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
...
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.show-sql=true

添加Repository和Entity

Repository在DDD中是一個非常重要的概念,字面意思來講它就是一個倉庫。它屏蔽了SQL和數據庫操作的細節,使得業務代碼無需再考慮更細節的數據處理。它和Mybatis可以說是兩個完全相反的流派。

Spring Data JPA中,默認實現了Crud操作的Repository,可以直接繼承並使用這個框架進行快速的CRUD實現。

package com.spring.demo.demo.repo.repository;

import com.spring.demo.demo.repo.entity.User;
...

@Repository
public interface UserRepository extends CrudRepository<User, Integer> { }

對應數據庫中的數據表,會有一個實體Entity來定義它的表結構。

package com.spring.demo.demo.repo.entity;

import javax.persistence.*;

@Entity
@Table(name="t_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private Integer gender;

    // Getter & Setter
    ...
}

在Service調用中,即可簡單的使用save方法來保存新的User數據。

package com.spring.demo.demo.service;

import com.spring.demo.demo.repo.entity.User;
...

@Service
public class UserService implements  IUserService {

    @Autowired
    UserRepository userRepo;

    public String findUser(int id) {
        return "用戶" + id;
    }

    public User createUser(User user) {
        return userRepo.save(user);
    }
}

最後在Controller中,修改Service方法並創建User。

package com.spring.demo.demo.controller;

import com.spring.demo.demo.dto.UserCreateRequest;
...

@RestController
public class UserController {

    @Autowired
    IUserService userService;

    @RequestMapping("/user/{id}")
    public String find(@PathVariable int id) {
        return userService.findUser(id);
    }

    @PostMapping("/user")
    public void create(@RequestBody @Validated UserCreateRequest userReq) {

        User user = new User();
        user.setName(userReq.getName());
        user.setGender(userReq.getGender());

        user = userService.createUser(user);
        System.out.println("創建用戶 ID=" + user.getId() + " 用戶名=" + user.getName());
    }
}

重啓Spring並提交創建請求。

$ curl -XPOST 'http://127.0.0.1:8080/user' -H 'Content-Type: application/json' -d'{"name":"用戶A","gender":0}'

可以看到,在console中有創建成功的提示信息。

Hibernate: insert into t_user (gender, name) values (?, ?)

創建用戶 ID=1 用戶名=用戶A

緩存

對於不常改變的數據,常常需要進行緩存以提高系統性能和增加系統吞吐量。對此,Spring Cache提供了緩存的基本實現。

添加依賴

修改pom.xml,添加對cache的支持。

  ...
  <dependencies>
    ...
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-cache</artifactId>
      <optional>true</optional>
    </dependency>
  </dependencies>

服務配置

修改/resources/application.properties,添加相關的設置。

...
spring.cache.type=simple

打開開關

需要在Application中,打開Cache開關。

package com.spring.demo.demo;

import org.springframework.boot.SpringApplication;
...

@SpringBootApplication
@EnableCaching
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

使用Cacheable標註

對於Cache內容,需要添加一個key名來保存內容。

package com.spring.demo.demo.service;

import com.spring.demo.demo.repo.entity.User;
...

@Service
public class UserService implements  IUserService {

    @Autowired
    UserRepository userRepo;

    @Cacheable(cacheNames = "user")
    public User findUser(Integer id) {
        System.out.println("取得用戶操作 ID=" + id);
        return userRepo.findById(id).get();
    }

    public User createUser(User user) {
        return userRepo.save(user);
    }
}

重啓Spring,發送GET請求後可以看到,只有第一次執行了SQL操作,說明緩存處理已經完成。

$ curl -XGET 'http://127.0.0.1:8080/user/1' 
$ 用戶A
$ 用戶A
> 取得用戶操作 ID=1=
> Hibernate: select user0_.id as id1_0_0_, user0_.gender as gender2_0_0_, user0_.name as name3_0_0_ from t_user user0_ where user0_.id=?

Redis

Spring的默認Cache處理並不使用Redis,要使用Redis作爲緩存應用,需要添加Redis的框架支持。

添加依賴

修改pom.xml,添加對cache的支持。

  ...
  <dependencies>
    ...
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
  </dependencies>

服務配置

修改/resources/application.properties,添加相關的設置。

...
spring.redis.host=127.0.0.1
spring.redis.password=123456
spring.redis.port=6379
spring.redis.jedis.pool.max-active=8

序列化對象

由於要保存到redis中,保存的實體對象需要進行序列化。

package com.spring.demo.demo.repo.entity;

import java.io.Serializable;
...

@Entity
@Table(name="t_user")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private Integer gender;

    // Getter & Setter
    ...
}

重啓Spring,再試一遍上節的操作,仍然是一樣的結果,但緩存已經換爲redis。

$ curl -XGET 'http://127.0.0.1:8080/user/1' 
$ 用戶A
$ 用戶A
> 取得用戶操作 ID=1
> Hibernate: select user0_.id as id1_0_0_, user0_.gender as gender2_0_0_, user0_.name as name3_0_0_ from t_user user0_ where user0_.id=?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章