使用MongoDB
需要在Spring Boot應用中使用MongoDB,可以在pom.xml中添加spring-boot-starter-data-mongodb
依賴,這樣Spring Boot會自動配置MongoDB的相關bean,比如MongoClient、MongoTemplate等,可以參考Spring Data MongoDB的自動配置類org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
的API文檔或源碼。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
默認配置的MongoDB連接對應的主機是localhost,端口號是標準端口號27017,database是test。可以通過spring.data.mongodb
打頭的配置屬性進行配置,對應的屬性將綁定到org.springframework.boot.autoconfigure.mongo.MongoProperties
對象,下面的代碼重新配置了主機、端口號和database。更多配置信息可以參考MongoProperties
的API文檔或源代碼。
spring.data.mongodb.host=10.192.48.170
spring.data.mongodb.port=27017
spring.data.mongodb.database=test_db
之後就可以直接通過MongoTemplate進行MongoDB的操作了。下面的代碼中定義了一個User類,其userId屬性對應MongoDB的user這個document的id屬性,username屬性對應於MongoDB的user這個document的user_name屬性。然後在測試類中,new了一個User對象,通過MongoTemplate對象把它存入到了MongoDB中。
@Document
@Data
public class User {
@Id
private Long userId;
private String name;
@Field("user_name")
private String username;
}
@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void testSave() {
User user = new User();
user.setUserId(2L);
user.setName("張三");
user.setUsername("zhangsan");
this.mongoTemplate.save(user);
}
}
也可以定義Spring Data Repository,通過Repository對MongoDB進行訪問。定義的Repository,Spring Boot將自動對其進行掃描,由org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration
定義,掃描路徑是Spring Boot啓動類所在的包。有需要也可以手動加上@EnableMongoRepositories
以指定需要掃描的路徑。下面的代碼定義了一個UserRepository,其繼承自標準的MongoRepository,同時又按照Spring Data的規範定義了一個findByName方法。
public interface UserRepository extends MongoRepository<User, Long> {
List<User> findByName(String name);
}
之後可以直接在需要的地方注入UserRepository,通過UserRepository訪問MongoDB,下面的代碼中就分別利用注入的UserRepository進行了User對象的新增和查詢操作。
@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
@Autowired
private UserRepository userRepository;
@Test
public void testSave() {
User user = new User();
user.setUserId(3L);
user.setName("張三");
user.setUsername("zhangsan");
this.userRepository.save(user);
}
@Test
public void testFindByName() {
List<User> users = this.userRepository.findByName("張三");
Assert.assertNotNull(users);
Assert.assertEquals("張三", users.get(0).getName());
}
}
本文旨在描述在Spring Boot應用中如何使用MongoDB,所以對Spring Data MongoDB的內容沒有講解太多。
基於Reactive編程
如果期望基於Reactive編程則可以引入spring-boot-starter-data-mongodb-reactive
依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
引入該依賴後Spring Boot將自動配置一個ReactiveMongoTemplate,它默認使用Reactor實現進行Reactive編程。我們可以直接在應用中注入ReactiveMongoTemplate實例,通過它進行相關Reactive操作。下面的代碼展示了通過ReactiveMongoTemplate進行User對象的保存操作。
@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
@Autowired
private ReactiveMongoTemplate reactiveMongoTemplate;
@Test
public void testReactive() {
User user = new User();
user.setUserId(4L);
user.setName("李四");
user.setUsername("lisi");
Mono<User> mono = this.reactiveMongoTemplate.save(user);
mono.block();
}
}
Repository中的相關操作也是可以基於Reactive的,這需要我們定義的Repository繼承自下面的四個接口之一,其中前面兩個是基於Reactor實現,後面兩個是基於RxJava2實現。以SortingRepository結尾的Repository都繼承自對應的CrudRepository。
- ReactiveCrudRepository
- ReactiveSortingRepository
- RxJava2CrudRepository
- RxJava2SortingRepository
添加了spring-boot-starter-data-mongodb-reactive
依賴後,會自動添加Reactor依賴,所以可以直接使用ReactiveCrudRepository和ReactiveSortingRepository。下面的代碼中定義的ReactiveUserRepository就是基於ReactiveSortingRepository實現的,同時擴展了一個查詢操作findByUsername
,其返回結果是Reactor實現的Flux。
public interface ReactiveUserRepository extends ReactiveSortingRepository<User, Long> {
Flux<User> findByUsername(String username);
}
上面定義的ReactiveUserRepository也會被自動掃描到,並被註冊爲Spring bean,在程序中可以直接注入ReactiveUserRepository對象進行使用,比如下面代碼這樣。
@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
@Autowired
private ReactiveUserRepository reactiveUserRepository;
@Test
public void testReactiveUserRepository() throws Exception {
User user = new User();
user.setUserId(System.currentTimeMillis());
user.setName("李四");
user.setUsername("lisi");
Mono<User> mono = this.reactiveUserRepository.save(user);
mono.subscribe(u -> System.out.println("saved success : " + u));
//get users by username
Flux<User> flux = this.reactiveUserRepository.findByUsername("lisi");
flux.subscribe(System.out::println);
TimeUnit.SECONDS.sleep(1);
}
}
如果需要使用RxJava2CrudRepository和RxJava2SortingRepository,則需要引入RxJava2的依賴。
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
</dependency>
之後可以像使用ReactiveCrudRepository一樣使用它們。下面的代碼定義了一個基於RxJava2的Repository,同時擴展了一個findByUsername
查詢,返回類型是RxJava2實現的Flowable。
public interface RxJava2UserRepository extends RxJava2SortingRepository<User, Long> {
Flowable<User> findByUsername(String username);
}
它也可以直接被掃描和定義爲一個Spring bean,所以也可以直接在程序中進行注入。
@SpringBootTest(classes=Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
@Autowired
private RxJava2UserRepository rxJava2UserRepository;
@Test
public void testRxJava2UserRepository() throws Exception {
User user = new User();
user.setUserId(System.currentTimeMillis());
user.setName("李四");
user.setUsername("lisi");
Single<User> single = this.rxJava2UserRepository.save(user);
System.out.println("saved success : " + single.blockingGet());
//get users by username
Flowable<User> flowable = this.rxJava2UserRepository.findByUsername("lisi");
flowable.subscribe(System.out::println);
TimeUnit.SECONDS.sleep(1);
}
}
(注:本文是基於Spring Boot 2.0.3所寫)