SpringBoot2.x系列教程75--SpringBoot整合JPA、Redis實現分佈式的Session共享
一.SpringBoot整合JPA、Redis實現分佈式的Session共享
1. 創建web項目
我們按照之前的經驗,創建一個web程序,並將之改造成Spring Boot項目,具體過程略。
2.添加依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 改造:添加sql相關的依賴-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.39</version>
</dependency>
3.創建application.yml配置文件
server:
port: 8080
servlet:
#設置session過期時間
session:
timeout: "PT10M"
spring:
application:
name: spring-session-jpa
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: syc
url: jdbc:mysql://localhost:3306/spring-security?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&serverTimezone=UTC
redis:
host: localhost
port: 6379
database: 0
jedis:
pool:
max-idle: 8
min-idle: 0
max-active: 8
session:
#設置session存儲類型
store-type: redis
jpa:
database: mysql
show-sql: true #開發階段,打印要執行的sql語句.
hibernate:
ddl-auto: update
4.創建User實體類
package com.yyg.boot.entity;
import ch.qos.logback.classic.db.names.TableName;
import lombok.Data;
import lombok.ToString;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/29
* @Description Description
*/
@Entity
@Table(name="user")
@Data
@ToString
public class User implements Serializable {
@Id
@GeneratedValue(generator = "idGenerator",strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
@NotBlank(message = "username can not be empty")
private String username;
@Column(name = "password")
@NotBlank(message = "password can not be empty")
private String password;
}
5.創建UserRepository倉庫類
package com.yyg.boot.repository;
import com.yyg.boot.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/29
* @Description Description
*/
public interface UserRepository extends JpaRepository<User,Long> {
User findByUsername(String username);
User findByUsernameAndPassword(String username,String password);
}
6.創建Service實現類
6.1 創建UserService接口
package com.yyg.boot.service;
import com.yyg.boot.entity.User;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/29
* @Description Description
*/
public interface UserService {
/**
* save user
*/
User saveUser(User user);
/**
* find user by account
*/
User findByUsername(String username);
/**
* user login
*/
User login(String username, String password);
}
6.2 創建UserServiceImpl實現類
package com.yyg.boot.service.impl;
import com.yyg.boot.entity.User;
import com.yyg.boot.repository.UserRepository;
import com.yyg.boot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/29
* @Description Description
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User saveUser(User user) {
return userRepository.save(user);
}
@Override
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
@Override
public User login(String username, String password) {
return userRepository.findByUsernameAndPassword(username, password);
}
}
7.創建UserController接口
package com.yyg.boot.web;
import com.yyg.boot.entity.User;
import com.yyg.boot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/29
* @Description Description
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* save user
*/
@PostMapping(value = "/save")
public User save(@RequestBody User user) {
return userService.saveUser(user);
}
/**
* find user by username
*/
@GetMapping(value = "/find/{username}")
public User findUser(@PathVariable String username) {
return userService.findByUsername(username);
}
/**
* user login
*/
@GetMapping(value = "/login")
public User login(String username, String password, HttpSession session) {
User user = userService.login(username, password);
if(user!=null){
session.setAttribute(session.getId(),user);
}
return user;
}
@GetMapping(value = "/logout")
public String logout(HttpSession session){
session.removeAttribute(session.getId());
return "user logout success";
}
}
8.添加攔截器,判斷session是否有效
package com.yyg.boot.config;
import com.alibaba.fastjson.JSON;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/28
* @Description 開啓Redis Http Session
*/
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisHttpSessionConfiguration implements WebMvcConfigurer {
/**
* 添加過濾接口
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SecurityInterceptor())
//排除攔截
.excludePathPatterns("/user/login")
.excludePathPatterns("/user/logout")
//攔截路徑
.addPathPatterns("/**");
}
/**
* 判斷session是否爲空,從而進行攔截放行
*/
@Configuration
public class SecurityInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
HttpSession session = request.getSession();
if (session.getAttribute(session.getId()) != null) {
return true;
}
response.getWriter().write(JSON.toJSONString("please login first"));
return false;
}
}
}
9.創建入口類
package com.yyg.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/28
* @Description Description
*/
@SpringBootApplication
public class SpringSessionJpaApplication {
public static void main(String[] args){
SpringApplication.run(SpringSessionJpaApplication.class,args);
}
}
10.完整項目結構
11.啓動項目,進行測試
我們在未登錄的情況下,直接根據用戶名查詢某個用戶信息,會看到瀏覽器提示我們先要進行登錄。
然後測試save接口,會發現也是提示先進行登錄纔可以。
此時我們進行登錄,登錄成功
然後我們再進行save或find接口的測試,會發現此時這些接口都已經可以正常訪問了。
數據庫中已經多了一個新的數據。
然後我們再退出登錄
然後重新測試查詢接口,會發現已經無法查詢用戶信息了,提示需要進行登錄纔可以。
再重新登錄後,我們可以再啓動8081這個新的進程,然後查詢tom這個用戶信息,會發現也查詢到了tom的用戶信息,說明我們已經實現了session的共享。
redis中也有了保存的session信息。