SpringBoot整合Shiro和Redis的示例代碼
此demo用SpringBoot+Shiro簡單實現(xiàn)了登陸、注冊、認(rèn)證、授權(quán)的功能,并用redis做分布式緩存提高性能。
1.準(zhǔn)備工作
導(dǎo)入pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<groupId>com.ego</groupId>
<artifactId>shirodemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
<!-- 引入jsp依賴 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- Druid數(shù)據(jù)源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 引入redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
</project>
配置yml文件
spring:
# 設(shè)置視圖模板為jsp
mvc:
view:
prefix: /
suffix: .jsp
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC
username: root
password: root
# 監(jiān)控統(tǒng)計攔截的filters
filters: stat,wall,log4j,config
# 配置初始化大小/最小/最大
initial-size: 5
min-idle: 5
max-active: 20
# 獲取連接等待超時時間
max-wait: 60000
# 間隔多久進行一次檢測,檢測需要關(guān)閉的空閑連接
time-between-eviction-runs-millis: 60000
# 一個連接在池中最小生存的時間
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打開PSCache,并指定每個連接上PSCache的大小。oracle設(shè)為true,mysql設(shè)為false。分庫分表較多推薦設(shè)置為false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
redis:
host: 127.0.0.1
port: 6379
password: abc123456
database: 0
mybatis-plus:
type-aliases-package: com.ego.pojo
configuration:
map-underscore-to-camel-case: true
2.編寫index,login,register三個JSP
<%--解決頁面亂碼--%>
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用戶名:<input type="text" name="username" > <br/>
密碼 : <input type="text" name="password"> <br>
<input type="submit" value="登錄">
</form>
</body>
</html>
<%--解決頁面亂碼--%>
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index</title>
</head>
<body>
<h1>系統(tǒng)主頁</h1>
<a href="${pageContext.request.contextPath}/user/logout">退出用戶</a>
<ul>
<%-- admin角色的用戶能同時擁有用戶管理和訂單管理的權(quán)限,user角色的用戶只擁有訂單管理的權(quán)限 --%>
<shiro:hasRole name="admin">
<li>
<a href="">用戶管理</a>
</li>
</shiro:hasRole>
<%-- admin角色的用戶對訂單有增刪改查的權(quán)限,user角色的用戶只能查看訂單 --%>
<shiro:hasAnyRoles name="admin,user">
<li>
<a href="">訂單管理</a>
<ul>
<shiro:hasPermission name="order:add:*">
<li><a href="">新增</a></li>
</shiro:hasPermission>
<shiro:hasPermission name="order:del:*">
<li><a href="">刪除</a></li>
</shiro:hasPermission>
<shiro:hasPermission name="order:upd:*">
<li><a href="">修改</a></li>
</shiro:hasPermission>
<shiro:hasPermission name="order:find:*">
<li><a href="">查詢</a></li>
</shiro:hasPermission>
</ul>
</li>
</shiro:hasAnyRoles>
</ul>
</body>
</html>
<%--解決頁面亂碼--%>
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>register</title>
</head>
<body>
<h1>用戶注冊</h1>
<form action="${pageContext.request.contextPath}/user/register" method="post">
用戶名:<input type="text" name="username" > <br/>
密碼 : <input type="text" name="password"> <br>
<input type="submit" value="立即注冊">
</form>
</body>
</html>
3.實現(xiàn)User、Role、Permission三個POJO
package com.ego.pojo;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* @author 袁夢達 2019012364
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_user")
@ApiModel("用戶實體類")
public class User implements Serializable {
/** 數(shù)據(jù)庫中設(shè)置該字段自增時該注解不能少 **/
@TableId(type = IdType.AUTO)
@ApiModelProperty(name = "id", value = "ID 主鍵")
private Integer id;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "username", value = "用戶名")
private String username;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "password", value = "密碼")
private String password;
@TableField(fill = FieldFill.INSERT)
@ApiModelProperty(name = "salt", value = "鹽")
private String salt;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "age", value = "年齡")
private Integer age;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "email", value = "郵箱")
private String email;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "address", value = "地址")
private String address;
@TableField(exist = false)
private List<Role> roles = new ArrayList<>();
}
package com.ego.pojo;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* @author 袁夢達 2019012364
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_role")
@ApiModel("角色實體類")
public class Role implements Serializable {
/** 數(shù)據(jù)庫中設(shè)置該字段自增時該注解不能少 **/
@TableId(type = IdType.AUTO)
@ApiModelProperty(name = "id", value = "ID 主鍵")
private Integer id;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "name", value = "角色名稱")
private String name;
@TableField(exist = false)
private List<Permission> permissions = new ArrayList<>();
}
package com.ego.pojo;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 袁夢達 2019012364
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_permission")
@ApiModel("權(quán)限實體類")
public class Permission implements Serializable {
/** 數(shù)據(jù)庫中設(shè)置該字段自增時該注解不能少 **/
@TableId(type = IdType.AUTO)
@ApiModelProperty(name = "id", value = "ID主鍵")
private Integer id;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "name", value = "權(quán)限名稱")
private String name;
@TableField(fill = FieldFill.INSERT_UPDATE)
@ApiModelProperty(name = "url", value = "權(quán)限菜單URL")
private String url;
}
4.實現(xiàn)Controller、Service、Dao
這里dao采用了mybatis-plus
package com.ego.controller;
import com.ego.pojo.User;
import com.ego.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 袁夢達 2019012364
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 用戶登錄
* @param username
* @param password
* @return
*/
@RequestMapping("/login")
public String login(String username,String password){
// 獲取當(dāng)前登錄用戶
Subject subject = SecurityUtils.getSubject();
try {
// 執(zhí)行登錄操作
subject.login(new UsernamePasswordToken(username,password));
// 認(rèn)證通過后直接跳轉(zhuǎn)到index.jsp
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用戶名錯誤!");
} catch (IncorrectCredentialsException e) {
System.out.println("密碼錯誤!");
} catch (Exception e) {
}
// 如果認(rèn)證失敗仍然回到登錄頁面
return "redirect:/login.jsp";
}
@RequestMapping("/logout")
public String logout(){
subject.logout();
// 退出后仍然會到登錄頁面
* 用戶注冊
* @param user
@RequestMapping("/register")
public String register(User user){
userService.register(user);
return "redirect:/login.jsp";
return "redirect:/register.jsp";
}
package com.ego.service.impl;
import com.ego.dao.mapper.UserMapper;
import com.ego.shiro.ShiroConstant;
import com.ego.utils.SaltUtil;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
@Override
public void register(User user) {
//生成隨機鹽
String salt = SaltUtil.getSalt(ShiroConstant.SALT_LENGTH);
//保存隨機鹽
user.setSalt(salt);
//生成密碼
Md5Hash password = new Md5Hash(user.getPassword(), salt, ShiroConstant.HASH_ITERATORS);
//保存密碼
user.setPassword(password.toHex());
userMapper.insert(user);
public User findUserByUserName(String userName) {
return userMapper.findUserByUserName(userName);
import com.ego.dao.mapper.RoleMapper;
import com.ego.pojo.Role;
import com.ego.service.RoleService;
import java.util.List;
@Service("roleService")
public class RoleServiceImpl implements RoleService {
private RoleMapper roleMapper;
public List<Role> getRolesByUserId(Integer userId) {
return roleMapper.getRolesByUserId(userId);
import com.ego.dao.mapper.PermissionMapper;
import com.ego.pojo.Permission;
import com.ego.service.PermissionService;
@Service("permissionService")
public class PermissionServiceImpl implements PermissionService {
private PermissionMapper permissionMapper;
public List<Permission> getPermissionsByRoleId(Integer roleId) {
return permissionMapper.getPermissionsByRoleId(roleId);
package com.ego.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT u.id,u.username,u.password,u.salt,u.age,u.email,u.address FROM t_user u WHERE u.username = #{username}")
User findUserByUserName(String username);
public interface RoleMapper extends BaseMapper<Role> {
@Select("select r.id,r.name from t_role r left join t_user_role ur on ur.role_id = r.id where ur.user_id = #{userId}")
List<Role> getRolesByUserId(Integer userId);
public interface PermissionMapper extends BaseMapper<Permission> {
@Select("select p.id,p.name,p.url from t_permission p left join t_role_permission rp on rp.permission_id = p.id where rp.role_id = #{roleId}")
List<Permission> getPermissionsByRoleId(Integer roleId);
5.實現(xiàn)SaltUtil和ApplicationContextUtil兩個工具類
package com.ego.utils;
import java.util.Random;
/**
* @author 袁夢達 2019012364
*/
public class SaltUtil {
public static String getSalt(int n){
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
char aChar = chars[new Random().nextInt(chars.length)];
sb.append(aChar);
}
return sb.toString();
}
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
public static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
/**
* 根據(jù)工廠中的類名獲取類實例
*/
public static Object getBean(String beanName){
return context.getBean(beanName);
6.實現(xiàn)核心Shiro
package com.ego.utils;
import java.util.Random;
/**
* @author 袁夢達 2019012364
*/
public class SaltUtil {
public static String getSalt(int n){
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
char aChar = chars[new Random().nextInt(chars.length)];
sb.append(aChar);
}
return sb.toString();
}
}
package com.ego.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author 袁夢達 2019012364
*/
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
public static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
/**
* 根據(jù)工廠中的類名獲取類實例
*/
public static Object getBean(String beanName){
return context.getBean(beanName);
}
}
7.實現(xiàn)Redis分布式緩存
package com.ego.shiro;
import com.ego.shiro.cache.RedisCacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author 袁夢達 2019012364
*/
@Configuration
public class ShiroConfiguration {
//1.創(chuàng)建shiroFilter //負(fù)責(zé)攔截所有請求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//給filter設(shè)置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//配置系統(tǒng)受限資源
//配置系統(tǒng)公共資源
Map<String,String> map = new HashMap<String,String>();
map.put("/user/login", "anon");
map.put("/user/register","anon");
map.put("/register.jsp","anon");
map.put("/index.jsp","authc");//authc 請求這個資源需要認(rèn)證和授權(quán)
//默認(rèn)認(rèn)證界面路徑
shiroFilterFactoryBean.setLoginUrl("/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//2.創(chuàng)建安全管理器
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//給安全管理器設(shè)置
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
//3.創(chuàng)建自定義realm
public Realm getRealm(){
CustomerRealm customerRealm = new CustomerRealm();
// 設(shè)置密碼匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
// 設(shè)置加密方式
credentialsMatcher.setHashAlgorithmName(ShiroConstant.HASH_ALGORITHM_NAME.MD5);
// 設(shè)置散列次數(shù)
credentialsMatcher.setHashIterations(ShiroConstant.HASH_ITERATORS);
customerRealm.setCredentialsMatcher(credentialsMatcher);
// 設(shè)置緩存管理器
customerRealm.setCacheManager(new RedisCacheManager());
// 開啟全局緩存
customerRealm.setCachingEnabled(true);
// 開啟認(rèn)證緩存并指定緩存名稱
customerRealm.setAuthenticationCachingEnabled(true);
customerRealm.setAuthenticationCacheName("authenticationCache");
// 開啟授權(quán)緩存并指定緩存名稱
customerRealm.setAuthorizationCachingEnabled(true);
customerRealm.setAuthorizationCacheName("authorizationCache");
return customerRealm;
}
public class ShiroConstant {
/** 隨機鹽的位數(shù) **/
public static final int SALT_LENGTH = 8;
/** hash的散列次數(shù) **/
public static final int HASH_ITERATORS = 1024;
public interface HASH_ALGORITHM_NAME {
String MD5 = "MD5";
import com.ego.pojo.Permission;
import com.ego.pojo.Role;
import com.ego.pojo.User;
import com.ego.service.PermissionService;
import com.ego.service.RoleService;
import com.ego.service.UserService;
import com.ego.utils.ApplicationContextUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.util.List;
public class CustomerRealm extends AuthorizingRealm {
//授權(quán)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 獲取主身份信息
String principal = (String) principals.getPrimaryPrincipal();
// 根據(jù)主身份信息獲取角色信息
UserService userService = (UserService) ApplicationContextUtil.getBean("userService");
User user = userService.findUserByUserName(principal);
RoleService roleService = (RoleService) ApplicationContextUtil.getBean("roleService");
List<Role> roles = roleService.getRolesByUserId(user.getId());
if(!CollectionUtils.isEmpty(roles)){
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
roles.forEach(role -> {
simpleAuthorizationInfo.addRole(role.getName());
PermissionService permissionService = (PermissionService) ApplicationContextUtil.getBean("permissionService");
List<Permission> permissions = permissionService.getPermissionsByRoleId(role.getId());
if(!CollectionUtils.isEmpty(permissions)){
permissions.forEach(permission -> {
simpleAuthorizationInfo.addStringPermission(permission.getName());
});
}
});
return simpleAuthorizationInfo;
}
return null;
//認(rèn)證
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String principal = (String) token.getPrincipal();
if(!ObjectUtils.isEmpty(user)){
return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), new CustomerByteSource(user.getSalt()),this.getName());
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.util.ByteSource;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
//自定義salt實現(xiàn) 實現(xiàn)序列化接口
public class CustomerByteSource implements ByteSource, Serializable {
private byte[] bytes;
private String cachedHex;
private String cachedBase64;
public CustomerByteSource() {
public CustomerByteSource(byte[] bytes) {
this.bytes = bytes;
public CustomerByteSource(char[] chars) {
this.bytes = CodecSupport.toBytes(chars);
public CustomerByteSource(String string) {
this.bytes = CodecSupport.toBytes(string);
public CustomerByteSource(ByteSource source) {
this.bytes = source.getBytes();
public CustomerByteSource(File file) {
this.bytes = (new CustomerByteSource.BytesHelper()).getBytes(file);
public CustomerByteSource(InputStream stream) {
this.bytes = (new CustomerByteSource.BytesHelper()).getBytes(stream);
public static boolean isCompatible(Object o) {
return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
public byte[] getBytes() {
return this.bytes;
public boolean isEmpty() {
return this.bytes == null || this.bytes.length == 0;
public String toHex() {
if (this.cachedHex == null) {
this.cachedHex = Hex.encodeToString(this.getBytes());
return this.cachedHex;
public String toBase64() {
if (this.cachedBase64 == null) {
this.cachedBase64 = Base64.encodeToString(this.getBytes());
return this.cachedBase64;
public String toString() {
return this.toBase64();
public int hashCode() {
return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0;
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof ByteSource) {
ByteSource bs = (ByteSource) o;
return Arrays.equals(this.getBytes(), bs.getBytes());
} else {
return false;
private static final class BytesHelper extends CodecSupport {
private BytesHelper() {
public byte[] getBytes(File file) {
return this.toBytes(file);
public byte[] getBytes(InputStream stream) {
return this.toBytes(stream);
到此這篇關(guān)于SpringBoot整合Shiro和Redis的文章就介紹到這了,更多相關(guān)SpringBoot整合Shiro和Redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
web.xml中servlet, bean, filter, listenr 加載順序_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了web.xml中servlet, bean, filter, listenr 加載順序,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Ribbon負(fù)載均衡服務(wù)調(diào)用的示例詳解
Rbbo其實就是一個軟負(fù)載均衡的客戶端組件,他可以和其他所需請求的客戶端結(jié)合使用,這篇文章主要介紹了Ribbon負(fù)載均衡服務(wù)調(diào)用案例代碼,需要的朋友可以參考下2023-01-01
Java中final,finally,finalize三個關(guān)鍵字的區(qū)別_動力節(jié)點Java學(xué)院整理
這篇文章給大家收集整理了有關(guān)java中final,finally,finalize三個關(guān)鍵字的區(qū)別介紹,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧2017-04-04

