Spring boot與shiro集合實現許可權管理
一.資料庫表設計
表中的測試資料:
tb_user表如下,
pass_word是根據通過如下程式碼生成,根據使用者名稱和密碼生成md5值:
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
public class GenePd {
public static void main(String[] args) {
String hashAlgorithName = "MD5";
String password =
int hashIterations = 1024;//加密次數
ByteSource credentialsSalt = ByteSource.Util.bytes("admin");
Object obj = new SimpleHash(hashAlgorithName, password, credentialsSalt, hashIterations);
System.out.println(obj);
}
}
tb_role表如下:
tb_permission表如下:
tb_rp_relation表如下(tb_role與tb_permission的關聯關係):
tb_ru_relation表如下(tb_role與tb_user的關聯關係):
二、pom.xml檔案中新增依賴(下面是我工程裡填加的內容,可以根據自己專案只填加shiro部分內容):
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--junit測試依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version> 4.12</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
<!—swagger2工具的依賴,可以不用新增-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
</dependency>
<!-- devtools外掛,熱部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
<!--去掉spring boot內建的tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!--常用的工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!--spring的上下文工具包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
</dependencies>
三、專案設計:
1.domin部分:
2.dao層:
其中註解對映我是學習以下文章來寫:
https://blog.csdn.net/naruto_mr/article/details/48207437
@Mapper
public interface UserDAO {
@Select("select * from tb_user where user_name=#{username}")
@Results({
@Result(property="uid",column="uid",javaType=Integer.class),
@Result(property="user_name",column="user_name",javaType=String.class),
@Result(property="pass_word",column="pass_word",javaType=String.class),
@Result(property="roles",column="uid",[email protected](select="com.scap.web.demo.dao.UserDAO.findRolesByUid"))
})
User findByUsername(String username);
@Select("select r.* from tb_role r, tb_ru_relation re where r.rid=re.rid and uid=#{uid}")
@Results({
@Result(property = "rid",column = "rid",javaType = Integer.class),
@Result(property = "role_name",column = "role_name",javaType=String.class),
@Result(property = "permissions",column = "rid",[email protected](select = "com.scap.web.demo.dao.UserDAO.findPermissonsByRid"))
})
Role findRolesByUid(int uid);
@Select("select distinct p.* from tb_permission p,tb_rp_relation re where rid = #{rid}")
Permission findPermissonsByRid(int rid);
}
3.service層
@Service
public class UserService {
@Autowired
private UserDAO userDAO;
@Autowired
private HrPositionService hrPositionService;
public User findByUsername(String username) {
return userDAO.findByUsername(username);
}
}
4.junit測試
@RunWith(SpringRunner.class)
@SpringBootTest(classes= ScapApplication.class)
public class UserServiceImplTest {
@Autowired
private UserService userService;
@Test
public void findByUsername() {
User u = userService.findByUsername("test");
Set<Role> roleSet = u.getRoles();
for (Role role : roleSet){
Set<Permission> permissionSet = role.getPermissions();
for (Permission permission : permissionSet){
System.out.println(permission.getName());
}
System.out.println(role.getRole_name());
}
}
}
5.controller層
@Controller
public class UserController {
@Autowired
private UserService userService;
//使用者登入
@RequestMapping("/loginUser")
public String loginUser(@RequestParam("username") String username,
@RequestParam("password") String password,
HttpSession session) {
//把前端輸入的username和password封裝為token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
session.setAttribute("user", subject.getPrincipal());
return "index";
} catch (Exception e) {
e.printStackTrace();
return "login";
}
}
//退出登入
@RequestMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
subject.logout();
}
response.sendRedirect("http://test.ssa.jd.com/sso/logout?ReturnUrl=http://scap.jd.com:8080");
}
//訪問login時跳到login
@RequestMapping({"/login","/"})
public String login() {
//userService.getPositionRole();//獲得崗位名稱
String role = "admin";//臨時都給admin角色,後期改為根據崗位算出角色
UsernamePasswordToken token = new UsernamePasswordToken(role, "123456");
Subject subject = SecurityUtils.getSubject();
subject.login(token);
return "index";
}
//有admin角色才能訪問
@RequestMapping("/admin")
@ResponseBody
@RequiresRoles("admin")
public String admin() {
return "admin success";
}
//有develop角色才能訪問
@RequestMapping("/develop")
@ResponseBody
@RequiresRoles("develop")
public String develop() {
return "develop success";
}
//有delete許可權才能訪問
@RequestMapping("delete")
@ResponseBody
@RequiresPermissions("delete")
public String delete(){
return "delete success";
}
//訪問首頁時跳到index
@RequestMapping("/index")
public String index() {
return "index";
}
}
6.html
login.ftl
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>歡迎登入!</h1>
<form action="/loginUser" method="post">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
Index.ftl
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>歡迎登入,${user.username}</h1>
</body>
</html>
7.配置shiro
AutuRealm.java
package com.scap.web.demo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.springframework.beans.factory.annotation.Autowired;
import com.scap.web.demo.services.UserService;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import com.scap.web.demo.domin.User;
import com.scap.web.demo.domin.Role;
import com.scap.web.demo.domin.Permission;
import org.apache.shiro.util.ByteSource;
import java.util.*;
public class AutuRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
/**
* 為使用者授權
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//獲取前端輸入的使用者資訊,封裝為User物件
User userweb = (User) principals.getPrimaryPrincipal();
//獲取前端輸入的使用者名稱
String username = userweb.getUser_name();
//根據前端輸入的使用者名稱查詢資料庫中對應的記錄
User user = userService.findByUsername(username);
//如果資料庫中有該使用者名稱對應的記錄,就進行授權操作
if (user != null){
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//因為addRoles和addStringPermissions方法需要的引數型別是Collection
//所以先建立兩個collection集合
Collection<String> rolesCollection = new HashSet<String>();
Collection<String> perStringCollection = new HashSet<String>();
//獲取user的Role的set集合
Set<Role> roles = user.getRoles();
//遍歷集合
for (Role role : roles){
//將每一個role的name裝進collection集合
rolesCollection.add(role.getRole_name());
//獲取每一個Role的permission的set集合
Set<Permission> permissionSet = role.getPermissions();
//遍歷集合
for (Permission permission : permissionSet){
//將每一個permission的name裝進collection集合
perStringCollection.add(permission.getName());
}
//為使用者授權
info.addStringPermissions(perStringCollection);
}
//為使用者授予角色
info.addRoles(rolesCollection);
return info;
}else{
return null;
}
}
/**
* 認證登入
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//token攜帶了使用者資訊
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
//獲取前端輸入的使用者名稱
String userName = usernamePasswordToken.getUsername();
//根據使用者名稱查詢資料庫中對應的記錄
User user = userService.findByUsername(userName);
// User user = null;
//當前realm物件的name
String realmName = getName();
//鹽值
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUser_name());
//封裝使用者資訊,構建AuthenticationInfo物件並返回
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user, user.getPass_word(), credentialsSalt, realmName);
return authcInfo;
}
}
ShiroConfiguration.java
package com.scap.web.demo;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.LinkedHashMap;
@Configuration
public class ShiroConfiguration {
/**
* 密碼校驗規則HashedCredentialsMatcher
* 這個類是為了對密碼進行編碼的 ,
* 防止密碼在資料庫裡明碼儲存 , 當然在登陸認證的時候 ,
* 這個類也負責對form裡輸入的密碼進行編碼
* 處理認證匹配處理器:如果自定義需要實現繼承HashedCredentialsMatcher
*/
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密方式為MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//加密次數
credentialsMatcher.setHashIterations(1024);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
@Bean("authRealm")
@DependsOn("lifecycleBeanPostProcessor")//可選
public AutuRealm authRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) {
AutuRealm authRealm = new AutuRealm();
authRealm.setAuthorizationCachingEnabled(false);
authRealm.setCredentialsMatcher(matcher);
return authRealm;
}
/**
* 定義安全管理器securityManager,注入自定義的realm
* @param authRealm
* @return
*/
@Bean("securityManager")
public SecurityManager securityManager(@Qualifier("authRealm") AutuRealm authRealm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(authRealm);
return manager;
}
/**
* 定義shiroFilter過濾器並注入securityManager
* @param manager
* @return
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//設定securityManager
bean.setSecurityManager(manager);
//設定登入頁面
//可以寫路由也可以寫jsp頁面的訪問路徑
bean.setLoginUrl("/login");
//設定登入成功跳轉的頁面
bean.setSuccessUrl("/index");
//設定未授權跳轉的頁面
bean.setUnauthorizedUrl("/unauthorized");
//定義過濾器
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/index", "authc");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/loginUser", "anon");
filterChainDefinitionMap.put("/bootstrap/**", "anon");
filterChainDefinitionMap.put("/theme/**", "anon");
//需要登入訪問的資源 , 一般將/**放在最下邊
filterChainDefinitionMap.put("/**", "authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}
/**
* Spring的一個bean , 由Advisor決定對哪些類的方法進行AOP代理 .
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
/**
* 配置shiro跟spring的關聯
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
* lifecycleBeanPostProcessor是負責生命週期的 , 初始化和銷燬的類
* (可選)
*/
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
這塊需要注意一下,如果登陸頁有樣式,下面這個位置要把css,js等樣式的目錄過濾掉,否則最後整合shiro後,登陸頁的樣式會無法正常顯示
這樣就完成了spring boot對shrio的整合。
首先,我們用junit測試一下。執行UserServiceImplTest.java
控制檯如下顯示,說明test的角色在當前有view許可權。
四、執行
1.用test使用者,密碼123456可正常登陸,登陸後顯示“歡迎登入,test”
2.訪問admin會顯示成功,因為是admin的角色
3.訪問develop會不成功,因為不是develop的角色
4.訪問delete會不成功,因為沒有delete的許可權,我們在資料庫裡配置的是view許可權
以上說明我們springboot整合shiro成功!
相關推薦
Spring boot與shiro集合實現許可權管理
一.資料庫表設計 表中的測試資料: tb_user表如下, pass_word是根據通過如下程式碼生成,根據使用者名稱和密碼生成md5值: import org.apache.shiro.crypto.hash.SimpleHash; import org
spring boot 與 shiro的簡單整合使用
scheduler div turn map 用戶 ttr algorithm pen enc shrio官網:https://shiro.apache.org/ Apache Shiro是一個功能強大且易於使用的Java安全框架,可執行身份驗證,授權,加密和會話管理。借助
Apache Shiro(三)——Spring Boot 與 Shiro的 整合
在瞭解了Apache Shiro的架構、認證、授權之後,我們來看一下Shiro與Web的整合。下面以Spring Boot為例,介紹一下Spring Boot 與 Shiro的 整合。 一、建立一個Spring Boot專案 可以使用IDEA快速建立一個Spring Boot專
Spring專案整合ShiroFilter簡單實現許可權管理
Shiros是我們開發中常用的用來實現許可權控制的一種工具包,它主要有認證、授權、加密、會話管理、與Web整合、快取等功能。我是從事javaweb工作的,我就經常遇到需要實現許可權控制的專案,之前我們都是靠查詢資料獲取列表拼接展示的,還有的是及時的判斷許可權的問
如何使用Spring Boot與RabbitMQ結合實現延遲佇列
背景 何為延遲佇列? 顧名思義,延遲佇列就是進入該佇列的訊息會被延遲消費的佇列。而一般的佇列,訊息一旦入隊了之後就會被消費者馬上消費。 延遲佇列能做什麼?延遲佇列多用於需要延遲工作的場景。最常見的是以下兩種場景:延遲消費。比如: 使用者生成訂單之後
spring boot+thymeleaf+bootstrap 簡單實現後臺管理系統介面
最近在學spring boot ,學習一個框架無非也就是使用它來做以前做的事情,兩者比較才有不同,說一下自己使用的體會 先來說下spring boot ,微框架。快速開發,相當於零配置,從一個大神那看來的說:spring boot 相當於框架的框架 ,就是集成了很多,用哪個
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(十九):服務消費(Ribbon、Feign)
技術背景 上一篇教程中,我們利用Consul註冊中心,實現了服務的註冊和發現功能,這一篇我們來聊聊服務的呼叫。單體應用中,程式碼可以直接依賴,在程式碼中直接呼叫即可,但在微服務架構是分散式架構,服務都執行在各自的程序之中,甚至部署在不同的主機和不同的地區。這個時候就需要相關的遠端呼叫技術了。 Spring
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十):服務熔斷(Hystrix、Turbine)
線上演示 演示地址:http://139.196.87.48:9002/kitty 使用者名稱:admin 密碼:admin 雪崩效應 在微服務架構中,由於服務眾多,通常會涉及多個服務層級的呼叫,而一旦基礎服務發生故障,很可能會導致級聯故障,進而造成整個系統不可用,這種現象被稱為服務雪崩效應。服務雪崩
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十二):鏈路追蹤(Sleuth、Zipkin)
線上演示 演示地址:http://139.196.87.48:9002/kitty 使用者名稱:admin 密碼:admin 技術背景 在微服務架構中,隨著業務發展,系統拆分導致系統呼叫鏈路愈發複雜,一個看似簡單的前端請求可能最終需要呼叫很多次後端服務才能完成,那麼當整個請求出現問題時,我們很難得知到
Spring Boot 整合 Shiro實現許可權控制,親測可用,附帶sql
前提: 本文主要講解Spring Boot 與 Shiro的整合 與許可權控制的實現方式(主要以程式碼實現功能為主),主要用到的技術Spring Boot+Shiro+Jpa(通過Maven構建),並不會涉及到Shiro框架的原始碼分析 如果有想要學習Shiro框架的小夥伴可以去http://shiro.
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(十七):登入驗證碼實現(Captcha)
<el-form-item > <el-col :span="12"> <el-form-item prop="captcha"> <el-input type="test" v-model="loginForm.captcha" auto-
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(十八):服務註冊和發現(Consul)
什麼是 Consul Consul 是 HashiCorp 公司推出的開源工具,用於實現分散式系統的服務發現與配置。與其它分散式服務註冊與發現的方案,Consul 的方案更“一站式”,內建了服務註冊與發現框架、分佈一致性協議實現、健康檢查、Key/Value 儲存、多資料中心方案,不再需要依賴其它工具(比如
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十一):服務閘道器(Zuul)
線上演示 使用者名稱:admin 密碼:admin 技術背景 前面我們通過Ribbon或Feign實現了微服務之間的呼叫和負載均衡,那我們的各種微服務又要如何提供給外部應用呼叫呢。 當然,因為是REST API介面,外部客戶端直接呼叫各個微服務是沒有問題的,但出於種種原因,這並不是一個好的選擇。 讓客戶端直
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十三):配置中心(Config、Bus)
線上演示 使用者名稱:admin 密碼:admin 技術背景 如今微服務架構盛行,在分散式系統中,專案日益龐大,子專案日益增多,每個專案都散落著各種配置檔案,且隨著服務的增加而不斷增多。此時,往往某一個基礎服務資訊變更,都會導致一系列服務的更新和重啟,運維也是苦不堪言,而且還很容易出錯。於是,配置中心便由此
Spring Boot + Spring Cloud 實現許可權管理系統 後端篇(二十五):Spring Security 版本
線上演示 使用者名稱:admin 密碼:admin 技術背景 到目前為止,我們使用的許可權認證框架是 Shiro,雖然 Shiro 也足夠好用並且簡單,但對於 Spring 官方主推的安全框架 Spring Security,使用者群也是甚大的,所以我們這裡把當前的程式碼切分出一個 shiro-cloud
Spring Boot 整合Shiro實現登陸認證和許可權控制
我在做畢設的時候,使用了Shiro作為專案中的登陸認證和許可權控制。 下面是我專案中如何實現整合shiro的學習記錄。 匯入shiro依賴包到pom.xml <!-- Shiro依賴 --> <dependency>
Spring Boot 整合 Shiro實現認證及授權管理
Spring Boot Shiro 本示例要內容 基於RBAC,授權、認證 加密、解密 統一異常處理 redis session支援 介紹 Apache Shiro 是一個功能強大且易於使用的Java安全框架,可執行身份驗證,授權,加密和會話管理。藉助Shiro易於理解的API,您可以快速輕鬆地保護任何應
spring boot整合shiro 簡單許可權控制
package me.config; import javax.annotation.Resource; import me.domain.entity.CmsUser; import me.service.UserService; import me.utils.MD5Util
Spring Boot集成Hazelcast實現集群與分布式內存緩存
exe 端口 ava 客戶端訪問 oot cacheable nts app 區域 Hazelcast是Hazelcast公司開源的一款分布式內存數據庫產品,提供彈性可擴展、高性能的分布式內存計算。並通過提供諸如Map,Queue,ExecutorService,Lock和
spring boot中使用websocket實現點對點通訊與伺服器推送
WebSocket介紹 websocket是html中一種新的協議,它實現了真正的長連線,實現了瀏覽器與伺服器的全雙工通訊(指在通訊的任意時刻,線路上存在A到B和B到A的雙向訊號傳輸)。 現在我們接觸的協議大多是htttp協議,在瀏覽器中通過http協議實現了單向的通訊