1. Tổng quan
Trong hướng dẫn nhanh này, chúng ta sẽ khám phá cách sử dụng Spring Session được hỗ trợ bằng MongoDB, cả khi có và không có Spring Boot.
Spring Session cũng có thể được hỗ trợ bằng các cửa hàng khác như Redis và JDBC.
2. Cấu hình khởi động mùa xuân
Đầu tiên, chúng ta hãy xem xét các phụ thuộc và cấu hình cần thiết cho Spring Boot. Để bắt đầu, hãy thêm các phiên bản mới nhất của spring-session-data-mongodb và spring-boot-starter-data-mongodb cho dự án của chúng tôi:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
Sau đó, để kích hoạt cấu hình tự động Spring Boot, chúng tôi sẽ cần thêm loại cửa hàng Spring Session là mongodb trong application.properties :
spring.session.store-type=mongodb
3. Cấu hình mùa xuân không có khởi động mùa xuân
Bây giờ, chúng ta hãy xem xét các phụ thuộc và cấu hình cần thiết để lưu trữ phiên Spring trong MongoDB mà không cần Spring Boot.
Tương tự như cấu hình Spring Boot, chúng tôi sẽ cần spring-session-data-mongodb sự phụ thuộc. Tuy nhiên, ở đây chúng tôi sẽ sử dụng spring-data-mongodb sự phụ thuộc để truy cập cơ sở dữ liệu MongoDB của chúng tôi:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
Cuối cùng, hãy xem cách cấu hình ứng dụng:
@EnableMongoHttpSession
public class HttpSessionConfig {
@Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
return new JdkMongoSessionConverter(Duration.ofMinutes(30));
}
}
@ EnableMongoHttpSession chú thích cho phép cấu hình được yêu cầu để lưu trữ dữ liệu phiên trong MongoDB .
Ngoài ra, hãy lưu ý rằng JdkMongoSessionConverter chịu trách nhiệm tuần tự hóa và giải mã dữ liệu phiên.
4. Ứng dụng mẫu
Hãy tạo một ứng dụng để kiểm tra cấu hình. Chúng tôi sẽ sử dụng Spring Boot, vì nó nhanh hơn và yêu cầu ít cấu hình hơn.
Chúng tôi sẽ bắt đầu bằng cách tạo bộ điều khiển để xử lý các yêu cầu:
@RestController
public class SpringSessionMongoDBController {
@GetMapping("/")
public ResponseEntity<Integer> count(HttpSession session) {
Integer counter = (Integer) session.getAttribute("count");
if (counter == null) {
counter = 1;
} else {
counter++;
}
session.setAttribute("count", counter);
return ResponseEntity.ok(counter);
}
}
Như chúng ta có thể thấy trong ví dụ này, chúng tôi đang gia tăng bộ đếm trên mỗi lần truy cập đến điểm cuối và lưu trữ giá trị của nó trong một thuộc tính phiên có tên là count .
5. Kiểm tra ứng dụng
Hãy kiểm tra ứng dụng để xem liệu chúng tôi có thực sự có thể lưu trữ dữ liệu phiên trong MongoDB hay không.
Để làm như vậy, chúng tôi sẽ truy cập vào điểm cuối và kiểm tra cookie mà chúng tôi sẽ nhận được. Điều này sẽ chứa một id phiên.
Sau đó, chúng tôi sẽ truy vấn bộ sưu tập MongoDB để tìm nạp dữ liệu phiên bằng id phiên:
@Test
public void
givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {
HttpEntity<String> response = restTemplate
.exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
HttpHeaders headers = response.getHeaders();
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);
Assert.assertEquals(response.getBody(),
repository.findById(getSessionId(set_cookie)).getAttribute("count").toString());
}
private String getSessionId(String cookie) {
return new String(Base64.getDecoder().decode(cookie.split(";")[0].split("=")[1]));
}
6. Nó hoạt động như thế nào?
Hãy cùng nhìn lại những gì diễn ra trong hậu trường của buổi Spring.
SessionRepositoryFilter chịu trách nhiệm về hầu hết các công việc:
- chuyển đổi HttpSession thành một MongoSession
- kiểm tra xem có Cookie không hiện tại và nếu có, hãy tải dữ liệu phiên từ cửa hàng
- lưu dữ liệu phiên cập nhật trong cửa hàng
- kiểm tra tính hợp lệ của phiên
Ngoài ra, SessionRepositoryFilter tạo một cookie với tên SESSION đó là HttpOnly và an toàn. Cookie này chứa id phiên, là giá trị được mã hóa Base64.
Để tùy chỉnh tên hoặc thuộc tính cookie, chúng tôi sẽ phải tạo một Spring bean loại DefaultCookieSerializer.
Ví dụ:ở đây chúng tôi đang tắt httponly thuộc tính của cookie:
@Bean
public DefaultCookieSerializer customCookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setUseHttpOnlyCookie(false);
return cookieSerializer;
}
7. Chi tiết phiên được lưu trữ trong MongoDB
Hãy truy vấn bộ sưu tập phiên của chúng tôi bằng cách sử dụng lệnh sau trong bảng điều khiển MongoDB của chúng tôi:
db.sessions.findOne()
Do đó, chúng tôi sẽ nhận được một tài liệu BSON tương tự như:
{
"_id" : "5d985be4-217c-472c-ae02-d6fca454662b",
"created" : ISODate("2019-05-14T16:45:41.021Z"),
"accessed" : ISODate("2019-05-14T17:18:59.118Z"),
"interval" : "PT30M",
"principal" : null,
"expireAt" : ISODate("2019-05-14T17:48:59.118Z"),
"attr" : BinData(0,"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFY291bnRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAC3g=")
}
_id là một UUID sẽ được mã hóa Base64 bởi DefaultCookieSerializer và đặt làm giá trị trong SESSION bánh quy. Ngoài ra, hãy lưu ý rằng attr thuộc tính chứa giá trị thực của bộ đếm của chúng tôi.