SpringBoot + Shiro + JWT集成Redis緩存(Jedis)

序言

? ? 目錄:https://blog.csdn.net/wang926454/article/details/82971291

首先感謝SmithCruise提供的思路刘绣,文章地址:http://www.reibang.com/p/f37f8c295057

根據(jù)SmithCruise的項(xiàng)目進(jìn)行后續(xù)更新

? ? 將其改為數(shù)據(jù)庫(kù)形式(MySQL)

? ? 實(shí)現(xiàn)Shiro的Cache(Redis)功能

? ? 解決無法直接返回401錯(cuò)誤

? ? Token刷新(RefreshToken)

當(dāng)前博客源碼:https://download.csdn.net/download/wang926454/10726052

我的項(xiàng)目地址

? ? Github:https://github.com/wang926454/ShiroJwt

? ? Gitee(碼云):https://gitee.com/wang926454/ShiroJwt

實(shí)現(xiàn)Shiro的Cache(Redis)功能

主要參考

? ? https://blog.csdn.net/why15732625998/article/details/78729254

? ? http://www.cnblogs.com/GodHeng/p/9301330.html

? ? https://blog.csdn.net/W_Z_W_888/article/details/79979103

實(shí)現(xiàn)方式

? ? 建立JedisPool(啟動(dòng)注入JedisPool)

? ? Jedis操作Redis

? ? 重寫Shiro的Cache保存讀取

? ? 重寫Shiro緩存(Cache)管理器

JedisPool搭建

首先加入Jedis的Jar(Shiro的集成這里就不說了)

<!-- Redis-Jedis -->

<dependency>

? ? <groupId>redis.clients</groupId>

? ? <artifactId>jedis</artifactId>

? ? <version>2.9.0</version>

</dependency>

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

config.properties(Redis的配置屬性)

# Redis服務(wù)器地址

redis.host=127.0.0.1

# Redis服務(wù)器連接端口

redis.port=6379

# Redis服務(wù)器連接密碼(默認(rèn)為空)

redis.password=

# 連接超時(shí)時(shí)間(毫秒)

redis.timeout=10000

# 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)

redis.pool.max-active=200

# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)

redis.pool.max-wait=-1

# 連接池中的最大空閑連接

redis.pool.max-idle=8

# 連接池中的最小空閑連接

redis.pool.min-idle=0

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

JedisConfig.java(JedisPool啟動(dòng)配置Bean)

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

import redis.clients.jedis.JedisPool;

import redis.clients.jedis.JedisPoolConfig;

/**

* Jedis配置摄欲,項(xiàng)目啟動(dòng)注入JedisPool

* http://www.cnblogs.com/GodHeng/p/9301330.html

* @author Wang926454

* @date 2018/9/5 10:35

*/

@Configuration

@EnableAutoConfiguration

@PropertySource("classpath:config.properties")

@ConfigurationProperties(prefix = "redis")

public class JedisConfig {

? ? private static Logger logger = LoggerFactory.getLogger(JedisConfig.class);

? ? private String host;

? ? private int port;

? ? private String password;

? ? private int timeout;

? ? @Value("${redis.pool.max-active}")

? ? private int maxActive;

? ? @Value("${redis.pool.max-wait}")

? ? private int maxWait;

? ? @Value("${redis.pool.max-idle}")

? ? private int maxIdle;

? ? @Value("${redis.pool.min-idle}")

? ? private int minIdle;

? ? @Bean

? ? public JedisPool redisPoolFactory(){

? ? ? ? try {

? ? ? ? ? ? JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

? ? ? ? ? ? jedisPoolConfig.setMaxIdle(maxIdle);

? ? ? ? ? ? jedisPoolConfig.setMaxWaitMillis(maxWait);

? ? ? ? ? ? jedisPoolConfig.setMaxTotal(maxActive);

? ? ? ? ? ? jedisPoolConfig.setMinIdle(minIdle);

? ? ? ? ? ? // JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);

? ? ? ? ? ? JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, null);

? ? ? ? ? ? logger.info("初始化Redis連接池JedisPool成功!" + " Redis地址: " + host + ":" + port);

? ? ? ? ? ? return jedisPool;

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? logger.error("初始化Redis連接池JedisPool異常:" + e.getMessage());

? ? ? ? }

? ? ? ? return null;

? ? }

? ? public String getHost() {

? ? ? ? return host;

? ? }

? ? public void setHost(String host) {

? ? ? ? this.host = host;

? ? }

? ? public int getPort() {

? ? ? ? return port;

? ? }

? ? public void setPort(int port) {

? ? ? ? this.port = port;

? ? }

? ? public String getPassword() {

? ? ? ? return password;

? ? }

? ? public void setPassword(String password) {

? ? ? ? this.password = password;

? ? }

? ? public int getTimeout() {

? ? ? ? return timeout;

? ? }

? ? public void setTimeout(int timeout) {

? ? ? ? this.timeout = timeout;

? ? }

? ? public int getMaxActive() {

? ? ? ? return maxActive;

? ? }

? ? public void setMaxActive(int maxActive) {

? ? ? ? this.maxActive = maxActive;

? ? }

? ? public int getMaxWait() {

? ? ? ? return maxWait;

? ? }

? ? public void setMaxWait(int maxWait) {

? ? ? ? this.maxWait = maxWait;

? ? }

? ? public int getMaxIdle() {

? ? ? ? return maxIdle;

? ? }

? ? public void setMaxIdle(int maxIdle) {

? ? ? ? this.maxIdle = maxIdle;

? ? }

? ? public int getMinIdle() {

? ? ? ? return minIdle;

? ? }

? ? public void setMinIdle(int minIdle) {

? ? ? ? this.minIdle = minIdle;

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

? ? 24

? ? 25

? ? 26

? ? 27

? ? 28

? ? 29

? ? 30

? ? 31

? ? 32

? ? 33

? ? 34

? ? 35

? ? 36

? ? 37

? ? 38

? ? 39

? ? 40

? ? 41

? ? 42

? ? 43

? ? 44

? ? 45

? ? 46

? ? 47

? ? 48

? ? 49

? ? 50

? ? 51

? ? 52

? ? 53

? ? 54

? ? 55

? ? 56

? ? 57

? ? 58

? ? 59

? ? 60

? ? 61

? ? 62

? ? 63

? ? 64

? ? 65

? ? 66

? ? 67

? ? 68

? ? 69

? ? 70

? ? 71

? ? 72

? ? 73

? ? 74

? ? 75

? ? 76

? ? 77

? ? 78

? ? 79

? ? 80

? ? 81

? ? 82

? ? 83

? ? 84

? ? 85

? ? 86

? ? 87

? ? 88

? ? 89

? ? 90

? ? 91

? ? 92

? ? 93

? ? 94

? ? 95

? ? 96

? ? 97

? ? 98

? ? 99

? ? 100

? ? 101

? ? 102

? ? 103

? ? 104

? ? 105

? ? 106

? ? 107

? ? 108

? ? 109

? ? 110

? ? 111

? ? 112

? ? 113

? ? 114

? ? 115

? ? 116

? ? 117

? ? 118

? ? 119

? ? 120

? ? 121

? ? 122

? ? 123

? ? 124

? ? 125

? ? 126

? ? 127

JedisUtil(Jedis工具類)

import com.wang.exception.CustomException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

import java.util.Set;

/**

* JedisUtil(推薦存Byte數(shù)組,存Json字符串效率更慢)

* @author Wang926454

* @date 2018/9/4 15:45

*/

@Component

public class JedisUtil {

? ? /**

? ? * Logger

? ? */

? ? private static Logger logger = LoggerFactory.getLogger(JedisUtil.class);

? ? /**

? ? * Status-OK

? ? */

? ? public final static String OK = "OK";

? ? /**

? ? * 靜態(tài)注入JedisPool連接池

? ? * 本來是正常注入JedisUtil刊驴,可以在Controller和Service層使用姿搜,但是重寫Shiro的CustomCache無法注入JedisUtil

? ? * 現(xiàn)在改為靜態(tài)注入JedisPool連接池,JedisUtil直接調(diào)用靜態(tài)方法即可

? ? * https://blog.csdn.net/W_Z_W_888/article/details/79979103

? ? */

? ? private static JedisPool jedisPool;

? ? @Autowired

? ? public void setJedisPool(JedisPool jedisPool) {

? ? ? ? JedisUtil.jedisPool = jedisPool;

? ? }

? ? /**

? ? * 獲取Jedis實(shí)例

? ? * @param

? ? * @return redis.clients.jedis.Jedis

? ? * @author Wang926454

? ? * @date 2018/9/4 15:47

? ? */

? ? public static synchronized Jedis getJedis() {

? ? ? ? try {

? ? ? ? ? ? if (jedisPool != null) {

? ? ? ? ? ? ? ? Jedis resource = jedisPool.getResource();

? ? ? ? ? ? ? ? return resource;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? return null;

? ? ? ? ? ? }

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("獲取Jedis資源異常:" + e.getMessage());

? ? ? ? }

? ? }

? ? /**

? ? * 釋放Jedis資源

? ? * @param

? ? * @return void

? ? * @author Wang926454

? ? * @date 2018/9/5 9:16

? ? */

? ? public static void closePool() {

? ? ? ? try {

? ? ? ? ? ? jedisPool.close();

? ? ? ? }catch (Exception e){

? ? ? ? ? ? throw new CustomException("釋放Jedis資源異常:" + e.getMessage());

? ? ? ? }

? ? }

? ? /**

? ? * 獲取redis鍵值-object

? ? * @param key

? ? * @return java.lang.Object

? ? * @author Wang926454

? ? * @date 2018/9/4 15:47

? ? */

? ? public static Object getObject(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? byte[] bytes = jedis.get(key.getBytes());

? ? ? ? ? ? if(StringUtil.isNotNull(bytes)) {

? ? ? ? ? ? ? ? return SerializableUtil.unserializable(bytes);

? ? ? ? ? ? }

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("獲取Redis鍵值getObject方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return null;

? ? }

? ? /**

? ? * 設(shè)置redis鍵值-object

? ? * @param key

* @param value

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 15:49

? ? */

? ? public static String setObject(String key, Object value) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.set(key.getBytes(), SerializableUtil.serializable(value));

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("設(shè)置Redis鍵值setObject方法異常:key=" + key + " value=" + value + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 設(shè)置redis鍵值-object-expiretime

? ? * @param key

* @param value

* @param expiretime

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 15:50

? ? */

? ? public static String setObject(String key, Object value, int expiretime) {

? ? ? ? String result = "";

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? result = jedis.set(key.getBytes(), SerializableUtil.serializable(value));

? ? ? ? ? ? if(OK.equals(result)) {

? ? ? ? ? ? ? ? jedis.expire(key.getBytes(), expiretime);

? ? ? ? ? ? }

? ? ? ? ? ? return result;

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("設(shè)置Redis鍵值setObject方法異常:key=" + key + " value=" + value + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 獲取redis鍵值-Json

? ? * @param key

? ? * @return java.lang.Object

? ? * @author Wang926454

? ? * @date 2018/9/4 15:47

? ? */

? ? public static String getJson(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.get(key);

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("獲取Redis鍵值getJson方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 設(shè)置redis鍵值-Json

? ? * @param key

? ? * @param value

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 15:49

? ? */

? ? public static String setJson(String key, String value) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.set(key, value);

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("設(shè)置Redis鍵值setJson方法異常:key=" + key + " value=" + value + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 設(shè)置redis鍵值-Json-expiretime

? ? * @param key

? ? * @param value

? ? * @param expiretime

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 15:50

? ? */

? ? public static String setJson(String key, String value, int expiretime) {

? ? ? ? String result = "";

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? result = jedis.set(key, value);

? ? ? ? ? ? if(OK.equals(result)) {

? ? ? ? ? ? ? ? jedis.expire(key, expiretime);

? ? ? ? ? ? }

? ? ? ? ? ? return result;

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("設(shè)置Redis鍵值setJson方法異常:key=" + key + " value=" + value + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 刪除key

? ? * @param key

? ? * @return java.lang.Long

? ? * @author Wang926454

? ? * @date 2018/9/4 15:50

? ? */

? ? public static Long delKey(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.del(key.getBytes());

? ? ? ? }catch(Exception e) {

? ? ? ? ? ? throw new CustomException("刪除Redis的鍵delKey方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? }finally{

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * key是否存在

? ? * @param key

? ? * @return java.lang.Boolean

? ? * @author Wang926454

? ? * @date 2018/9/4 15:51

? ? */

? ? public static Boolean exists(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.exists(key.getBytes());

? ? ? ? }catch(Exception e) {

? ? ? ? ? ? throw new CustomException("查詢Redis的鍵是否存在exists方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? }finally{

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 模糊查詢獲取key集合

? ? * @param key

? ? * @return java.util.Set<java.lang.String>

? ? * @author Wang926454

? ? * @date 2018/9/6 9:43

? ? */

? ? public static Set<String> keysS(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.keys(key);

? ? ? ? }catch(Exception e) {

? ? ? ? ? ? throw new CustomException("模糊查詢Redis的鍵集合keysS方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? }finally{

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 模糊查詢獲取key集合

? ? * @param key

? ? * @return java.util.Set<java.lang.String>

? ? * @author Wang926454

? ? * @date 2018/9/6 9:43

? ? */

? ? public static Set<byte[]> keysB(String key) {

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? return jedis.keys(key.getBytes());

? ? ? ? }catch(Exception e) {

? ? ? ? ? ? throw new CustomException("模糊查詢Redis的鍵集合keysB方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? }finally{

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 獲取過期剩余時(shí)間

? ? * @param key

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/11 16:26

? ? */

? ? public static Long getExpireTime(String key) {

? ? ? ? Long result = -2L;

? ? ? ? Jedis jedis = null;

? ? ? ? try {

? ? ? ? ? ? jedis = jedisPool.getResource();

? ? ? ? ? ? result = jedis.ttl(key);

? ? ? ? ? ? return result;

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new CustomException("獲取Redis鍵過期剩余時(shí)間getExpireTime方法異常:key=" + key + " cause=" + e.getMessage());

? ? ? ? } finally {

? ? ? ? ? ? if(jedis != null) {

? ? ? ? ? ? ? ? jedis.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

? ? 24

? ? 25

? ? 26

? ? 27

? ? 28

? ? 29

? ? 30

? ? 31

? ? 32

? ? 33

? ? 34

? ? 35

? ? 36

? ? 37

? ? 38

? ? 39

? ? 40

? ? 41

? ? 42

? ? 43

? ? 44

? ? 45

? ? 46

? ? 47

? ? 48

? ? 49

? ? 50

? ? 51

? ? 52

? ? 53

? ? 54

? ? 55

? ? 56

? ? 57

? ? 58

? ? 59

? ? 60

? ? 61

? ? 62

? ? 63

? ? 64

? ? 65

? ? 66

? ? 67

? ? 68

? ? 69

? ? 70

? ? 71

? ? 72

? ? 73

? ? 74

? ? 75

? ? 76

? ? 77

? ? 78

? ? 79

? ? 80

? ? 81

? ? 82

? ? 83

? ? 84

? ? 85

? ? 86

? ? 87

? ? 88

? ? 89

? ? 90

? ? 91

? ? 92

? ? 93

? ? 94

? ? 95

? ? 96

? ? 97

? ? 98

? ? 99

? ? 100

? ? 101

? ? 102

? ? 103

? ? 104

? ? 105

? ? 106

? ? 107

? ? 108

? ? 109

? ? 110

? ? 111

? ? 112

? ? 113

? ? 114

? ? 115

? ? 116

? ? 117

? ? 118

? ? 119

? ? 120

? ? 121

? ? 122

? ? 123

? ? 124

? ? 125

? ? 126

? ? 127

? ? 128

? ? 129

? ? 130

? ? 131

? ? 132

? ? 133

? ? 134

? ? 135

? ? 136

? ? 137

? ? 138

? ? 139

? ? 140

? ? 141

? ? 142

? ? 143

? ? 144

? ? 145

? ? 146

? ? 147

? ? 148

? ? 149

? ? 150

? ? 151

? ? 152

? ? 153

? ? 154

? ? 155

? ? 156

? ? 157

? ? 158

? ? 159

? ? 160

? ? 161

? ? 162

? ? 163

? ? 164

? ? 165

? ? 166

? ? 167

? ? 168

? ? 169

? ? 170

? ? 171

? ? 172

? ? 173

? ? 174

? ? 175

? ? 176

? ? 177

? ? 178

? ? 179

? ? 180

? ? 181

? ? 182

? ? 183

? ? 184

? ? 185

? ? 186

? ? 187

? ? 188

? ? 189

? ? 190

? ? 191

? ? 192

? ? 193

? ? 194

? ? 195

? ? 196

? ? 197

? ? 198

? ? 199

? ? 200

? ? 201

? ? 202

? ? 203

? ? 204

? ? 205

? ? 206

? ? 207

? ? 208

? ? 209

? ? 210

? ? 211

? ? 212

? ? 213

? ? 214

? ? 215

? ? 216

? ? 217

? ? 218

? ? 219

? ? 220

? ? 221

? ? 222

? ? 223

? ? 224

? ? 225

? ? 226

? ? 227

? ? 228

? ? 229

? ? 230

? ? 231

? ? 232

? ? 233

? ? 234

? ? 235

? ? 236

? ? 237

? ? 238

? ? 239

? ? 240

? ? 241

? ? 242

? ? 243

? ? 244

? ? 245

? ? 246

? ? 247

? ? 248

? ? 249

? ? 250

? ? 251

? ? 252

? ? 253

? ? 254

? ? 255

? ? 256

? ? 257

? ? 258

? ? 259

? ? 260

? ? 261

? ? 262

? ? 263

? ? 264

? ? 265

? ? 266

? ? 267

? ? 268

? ? 269

? ? 270

? ? 271

? ? 272

? ? 273

? ? 274

? ? 275

? ? 276

? ? 277

? ? 278

? ? 279

? ? 280

? ? 281

? ? 282

? ? 283

? ? 284

? ? 285

? ? 286

? ? 287

? ? 288

? ? 289

? ? 290

? ? 291

? ? 292

? ? 293

? ? 294

? ? 295

? ? 296

? ? 297

? ? 298

? ? 299

? ? 300

? ? 301

? ? 302

? ? 303

? ? 304

? ? 305

? ? 306

? ? 307

? ? 308

? ? 309

? ? 310

? ? 311

? ? 312

? ? 313

? ? 314

? ? 315

? ? 316

? ? 317

? ? 318

? ? 319

? ? 320

? ? 321

? ? 322

? ? 323

? ? 324

? ? 325

? ? 326

? ? 327

? ? 328

SerializableUtil(JedisUtil用到)

import com.wang.exception.CustomException;

import java.io.*;

/**

* Serializable工具(JDK)(也可以使用Protobuf自行百度)

* @author Wang926454

* @date 2018/9/4 15:13

*/

public class SerializableUtil {

? ? /**

? ? * 序列化

? ? * @param object

? ? * @return byte[]

? ? * @author Wang926454

? ? * @date 2018/9/4 15:14

? ? */

? ? public static byte[] serializable(Object object) {

? ? ? ? ByteArrayOutputStream baos = null;

? ? ? ? ObjectOutputStream oos = null;

? ? ? ? try {

? ? ? ? ? ? baos = new ByteArrayOutputStream();

? ? ? ? ? ? oos = new ObjectOutputStream(baos);

? ? ? ? ? ? oos.writeObject(object);

? ? ? ? ? ? byte[] bytes = baos.toByteArray();

? ? ? ? ? ? return bytes;

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? throw new CustomException("SerializableUtil工具類序列化出現(xiàn)IOException異常");

? ? ? ? } finally {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if(oos != null) {

? ? ? ? ? ? ? ? ? ? oos.close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if(baos != null) {

? ? ? ? ? ? ? ? ? ? baos.close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (IOException e) {

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? /**

? ? * 反序列化

? ? * @param bytes

? ? * @return java.lang.Object

? ? * @author Wang926454

? ? * @date 2018/9/4 15:14

? ? */

? ? public static Object unserializable(byte[] bytes) {

? ? ? ? ByteArrayInputStream bais = null;

? ? ? ? ObjectInputStream ois = null;

? ? ? ? try {

? ? ? ? ? ? bais = new ByteArrayInputStream(bytes);

? ? ? ? ? ? ois = new ObjectInputStream(bais);

? ? ? ? ? ? return ois.readObject();

? ? ? ? } catch (ClassNotFoundException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? throw new CustomException("SerializableUtil工具類反序列化出現(xiàn)ClassNotFoundException異常");

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? throw new CustomException("SerializableUtil工具類反序列化出現(xiàn)IOException異常");

? ? ? ? } finally {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if(ois != null) {

? ? ? ? ? ? ? ? ? ? ois.close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if(bais != null) {

? ? ? ? ? ? ? ? ? ? bais.close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (IOException e) {

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

? ? 24

? ? 25

? ? 26

? ? 27

? ? 28

? ? 29

? ? 30

? ? 31

? ? 32

? ? 33

? ? 34

? ? 35

? ? 36

? ? 37

? ? 38

? ? 39

? ? 40

? ? 41

? ? 42

? ? 43

? ? 44

? ? 45

? ? 46

? ? 47

? ? 48

? ? 49

? ? 50

? ? 51

? ? 52

? ? 53

? ? 54

? ? 55

? ? 56

? ? 57

? ? 58

? ? 59

? ? 60

? ? 61

? ? 62

? ? 63

? ? 64

? ? 65

? ? 66

? ? 67

? ? 68

? ? 69

? ? 70

? ? 71

? ? 72

? ? 73

? ? 74

? ? 75

? ? 76

? ? 77

StringUtil(JedisUtil用到)

public class StringUtil {

? ? /**

? ? * 定義下劃線

? ? */

? ? private static final char UNDERLINE = '_';

? ? /**

? ? * String為空判斷(不允許空格)

? ? * @param str

? ? * @return boolean

? ? * @author Wang926454

? ? * @date 2018/9/4 14:49

? ? */

? ? public static boolean isBlank(String str) {

? ? ? ? return str == null || "".equals(str.trim());

? ? }

? ? /**

? ? * String不為空判斷(不允許空格)

? ? * @param str

? ? * @return boolean

? ? * @author Wang926454

? ? * @date 2018/9/4 14:51

? ? */

? ? public static boolean isNotBlank(String str) {

? ? ? ? return !isBlank(str);

? ? }

? ? /**

? ? * Byte數(shù)組為空判斷

? ? * @param bytes

? ? * @return boolean

? ? * @author Wang926454

? ? * @date 2018/9/4 15:39

? ? */

? ? public static boolean isNull(byte[] bytes){

? ? ? ? // 根據(jù)byte數(shù)組長(zhǎng)度為0判斷

? ? ? ? return bytes.length == 0 || bytes == null;

? ? }

? ? /**

? ? * Byte數(shù)組不為空判斷

? ? * @param bytes

? ? * @return boolean

? ? * @author Wang926454

? ? * @date 2018/9/4 15:41

? ? */

? ? public static boolean isNotNull(byte[] bytes) {

? ? ? ? return !isNull(bytes);

? ? }

? ? /**

? ? * 駝峰轉(zhuǎn)下劃線工具

? ? * @param param

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 14:52

? ? */

? ? public static String camelToUnderline(String param) {

? ? ? ? if (isNotBlank(param)) {

? ? ? ? ? ? int len = param.length();

? ? ? ? ? ? StringBuilder sb = new StringBuilder(len);

? ? ? ? ? ? for (int i = 0; i < len; ++i) {

? ? ? ? ? ? ? ? char c = param.charAt(i);

? ? ? ? ? ? ? ? if (Character.isUpperCase(c)) {

? ? ? ? ? ? ? ? ? ? sb.append(UNDERLINE);

? ? ? ? ? ? ? ? ? ? sb.append(Character.toLowerCase(c));

? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? sb.append(c);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? return sb.toString();

? ? ? ? } else {

? ? ? ? ? ? return "";

? ? ? ? }

? ? }

? ? /**

? ? * 下劃線轉(zhuǎn)駝峰工具

? ? * @param param

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 14:52

? ? */

? ? public static String underlineToCamel(String param) {

? ? ? ? if (isNotBlank(param)) {

? ? ? ? ? ? int len = param.length();

? ? ? ? ? ? StringBuilder sb = new StringBuilder(len);

? ? ? ? ? ? for (int i = 0; i < len; ++i) {

? ? ? ? ? ? ? ? char c = param.charAt(i);

? ? ? ? ? ? ? ? if (c == 95) {

? ? ? ? ? ? ? ? ? ? ++i;

? ? ? ? ? ? ? ? ? ? if (i < len) {

? ? ? ? ? ? ? ? ? ? ? ? sb.append(Character.toUpperCase(param.charAt(i)));

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? sb.append(c);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? return sb.toString();

? ? ? ? } else {

? ? ? ? ? ? return "";

? ? ? ? }

? ? }

? ? /**

? ? * 在字符串兩周添加''

? ? * @param param

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 14:53

? ? */

? ? public static String addSingleQuotes(String param) {

? ? ? ? return "\'" + param + "\'";

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

? ? 24

? ? 25

? ? 26

? ? 27

? ? 28

? ? 29

? ? 30

? ? 31

? ? 32

? ? 33

? ? 34

? ? 35

? ? 36

? ? 37

? ? 38

? ? 39

? ? 40

? ? 41

? ? 42

? ? 43

? ? 44

? ? 45

? ? 46

? ? 47

? ? 48

? ? 49

? ? 50

? ? 51

? ? 52

? ? 53

? ? 54

? ? 55

? ? 56

? ? 57

? ? 58

? ? 59

? ? 60

? ? 61

? ? 62

? ? 63

? ? 64

? ? 65

? ? 66

? ? 67

? ? 68

? ? 69

? ? 70

? ? 71

? ? 72

? ? 73

? ? 74

? ? 75

? ? 76

? ? 77

? ? 78

? ? 79

? ? 80

? ? 81

? ? 82

? ? 83

? ? 84

? ? 85

? ? 86

? ? 87

? ? 88

? ? 89

? ? 90

? ? 91

? ? 92

? ? 93

? ? 94

? ? 95

? ? 96

? ? 97

? ? 98

? ? 99

? ? 100

? ? 101

? ? 102

? ? 103

? ? 104

? ? 105

? ? 106

? ? 107

? ? 108

? ? 109

? ? 110

? ? 111

? ? 112

? ? 113

? ? 114

? ? 115

? ? 116

重寫Shiro的Cache保存讀取和Shiro的Cache管理器

CustomCache.java(Cache保存讀取)

import com.wang.util.JWTUtil;

import com.wang.util.JedisUtil;

import com.wang.util.SerializableUtil;

import org.apache.shiro.cache.Cache;

import org.apache.shiro.cache.CacheException;

import java.util.*;

/**

* 重寫Shiro的Cache保存讀取

* @author Wang926454

* @date 2018/9/4 17:31

*/

public class CustomCache<K,V> implements Cache<K,V> {

? ? /**

? ? * redis-key-前綴-shiro:cache:

? ? */

? ? public final static String PREFIX_SHIRO_CACHE = "shiro:cache:";

? ? /**

? ? * 過期時(shí)間-5分鐘

? ? */

? ? private static final Integer EXPIRE_TIME = 5 * 60 * 1000;

? ? /**

? ? * 緩存的key名稱獲取為shiro:cache:account

? ? * @param key

? ? * @return java.lang.String

? ? * @author Wang926454

? ? * @date 2018/9/4 18:33

? ? */

? ? private String getKey(Object key){

? ? ? ? return PREFIX_SHIRO_CACHE + JWTUtil.getUsername(key.toString());

? ? }

? ? /**

? ? * 獲取緩存

? ? */

? ? @Override

? ? public Object get(Object key) throws CacheException {

? ? ? ? if(!JedisUtil.exists(this.getKey(key))){

? ? ? ? ? ? return null;

? ? ? ? }

? ? ? ? return JedisUtil.getObject(this.getKey(key));

? ? }

? ? /**

? ? * 保存緩存

? ? */

? ? @Override

? ? public Object put(Object key, Object value) throws CacheException {

? ? ? ? // 設(shè)置Redis的Shiro緩存

? ? ? ? return JedisUtil.setObject(this.getKey(key), value, EXPIRE_TIME);

? ? }

? ? /**

? ? * 移除緩存

? ? */

? ? @Override

? ? public Object remove(Object key) throws CacheException {

? ? ? ? if(!JedisUtil.exists(this.getKey(key))){

? ? ? ? ? ? return null;

? ? ? ? }

? ? ? ? JedisUtil.delKey(this.getKey(key));

? ? ? ? return null;

? ? }

? ? /**

? ? * 清空所有緩存

? ? */

? ? @Override

? ? public void clear() throws CacheException {

? ? ? ? JedisUtil.getJedis().flushDB();

? ? }

? ? /**

? ? * 緩存的個(gè)數(shù)

? ? */

? ? @Override

? ? public int size() {

? ? ? ? Long size = JedisUtil.getJedis().dbSize();

? ? ? ? return size.intValue();

? ? }

? ? /**

? ? * 獲取所有的key

? ? */

? ? @Override

? ? public Set keys() {

? ? ? ? Set<byte[]> keys = JedisUtil.getJedis().keys(new String("*").getBytes());

? ? ? ? Set<Object> set = new HashSet<Object>();

? ? ? ? for (byte[] bs : keys) {

? ? ? ? ? ? set.add(SerializableUtil.unserializable(bs));

? ? ? ? }

? ? ? ? return set;

? ? }

? ? /**

? ? * 獲取所有的value

? ? */

? ? @Override

? ? public Collection values() {

? ? ? ? Set keys = this.keys();

? ? ? ? List<Object> values = new ArrayList<Object>();

? ? ? ? for (Object key : keys) {

? ? ? ? ? ? values.add(JedisUtil.getObject(this.getKey(key)));

? ? ? ? }

? ? ? ? return values;

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

? ? 24

? ? 25

? ? 26

? ? 27

? ? 28

? ? 29

? ? 30

? ? 31

? ? 32

? ? 33

? ? 34

? ? 35

? ? 36

? ? 37

? ? 38

? ? 39

? ? 40

? ? 41

? ? 42

? ? 43

? ? 44

? ? 45

? ? 46

? ? 47

? ? 48

? ? 49

? ? 50

? ? 51

? ? 52

? ? 53

? ? 54

? ? 55

? ? 56

? ? 57

? ? 58

? ? 59

? ? 60

? ? 61

? ? 62

? ? 63

? ? 64

? ? 65

? ? 66

? ? 67

? ? 68

? ? 69

? ? 70

? ? 71

? ? 72

? ? 73

? ? 74

? ? 75

? ? 76

? ? 77

? ? 78

? ? 79

? ? 80

? ? 81

? ? 82

? ? 83

? ? 84

? ? 85

? ? 86

? ? 87

? ? 88

? ? 89

? ? 90

? ? 91

? ? 92

? ? 93

? ? 94

? ? 95

? ? 96

? ? 97

? ? 98

? ? 99

? ? 100

? ? 101

? ? 102

? ? 103

? ? 104

? ? 105

? ? 106

? ? 107

? ? 108

? ? 109

? ? 110

CustomCacheManager.java(緩存(Cache)管理器)

import org.apache.shiro.cache.Cache;

import org.apache.shiro.cache.CacheException;

import org.apache.shiro.cache.CacheManager;

/**

* 重寫Shiro緩存管理器

* @author Wang926454

* @date 2018/9/4 17:41

*/

public class CustomCacheManager implements CacheManager {

? ? @Override

? ? public <K, V> Cache<K, V> getCache(String s) throws CacheException {

? ? ? ? return new CustomCache<K,V>();

? ? }

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

最后在Shiro的配置Bean里設(shè)置我們重寫的緩存(Cache)管理器

/**

* 配置使用自定義Realm,關(guān)閉Shiro自帶的session

* 詳情見文檔 http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29

* @param userRealm

* @return org.apache.shiro.web.mgt.DefaultWebSecurityManager

* @author Wang926454

* @date 2018/8/31 10:55

*/

@Bean("securityManager")

public DefaultWebSecurityManager getManager(UserRealm userRealm) {

? ? DefaultWebSecurityManager manager = new DefaultWebSecurityManager();

? ? // 使用自定義Realm

? ? manager.setRealm(userRealm);

? ? // 關(guān)閉Shiro自帶的session

? ? DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();

? ? DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();

? ? defaultSessionStorageEvaluator.setSessionStorageEnabled(false);

? ? subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);

? ? manager.setSubjectDAO(subjectDAO);

? ? // 設(shè)置自定義緩存(Cache)管理器

? ? manager.setCacheManager(new CustomCacheManager());

? ? return manager;

}

? ? 1

? ? 2

? ? 3

? ? 4

? ? 5

? ? 6

? ? 7

? ? 8

? ? 9

? ? 10

? ? 11

? ? 12

? ? 13

? ? 14

? ? 15

? ? 16

? ? 17

? ? 18

? ? 19

? ? 20

? ? 21

? ? 22

? ? 23

OK痪欲,我們現(xiàn)在可以在Realm的doGetAuthorizationInfo()方法打斷點(diǎn)看下請(qǐng)求第一次后Redis多了一條緩存數(shù)據(jù)悦穿,下次就不會(huì)再調(diào)用doGetAuthorizationInfo()方法,除非緩存失效

在這里插入圖片描述

當(dāng)前博客源碼:https://download.csdn.net/download/wang926454/10726052

我的項(xiàng)目地址

? ? Github:https://github.com/wang926454/ShiroJwt

? ? Gitee(碼云):https://gitee.com/wang926454/ShiroJwt

---------------------

作者:時(shí)間可以改變一切

來源:CSDN

原文:https://blog.csdn.net/wang926454/article/details/82978632

版權(quán)聲明:本文為博主原創(chuàng)文章业踢,轉(zhuǎn)載請(qǐng)附上博文鏈接栗柒!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市知举,隨后出現(xiàn)的幾起案子瞬沦,更是在濱河造成了極大的恐慌,老刑警劉巖雇锡,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逛钻,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡锰提,警方通過查閱死者的電腦和手機(jī)曙痘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來立肘,“玉大人边坤,你說我怎么就攤上這事×履辏” “怎么了茧痒?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)融蹂。 經(jīng)常有香客問我旺订,道長(zhǎng),這世上最難降的妖魔是什么超燃? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任区拳,我火速辦了婚禮,結(jié)果婚禮上淋纲,老公的妹妹穿的比我還像新娘劳闹。我一直安慰自己,他們只是感情好洽瞬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布本涕。 她就那樣靜靜地躺著,像睡著了一般伙窃。 火紅的嫁衣襯著肌膚如雪菩颖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天为障,我揣著相機(jī)與錄音晦闰,去河邊找鬼放祟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛呻右,可吹牛的內(nèi)容都是我干的跪妥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼声滥,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼眉撵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起落塑,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤纽疟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后憾赁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體污朽,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年龙考,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蟆肆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洲愤,死狀恐怖颓芭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柬赐,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布官紫,位于F島的核電站肛宋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏束世。R本人自食惡果不足惜酝陈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毁涉。 院中可真熱鬧沉帮,春花似錦、人聲如沸贫堰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽其屏。三九已至喇勋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偎行,已是汗流浹背川背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工贰拿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熄云。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓膨更,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親缴允。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荚守,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • RedisRedis命令參考網(wǎng)址:http://doc.redisfans.com/ Redis 簡(jiǎn)介Redis ...
    野柳閱讀 1,126評(píng)論 0 9
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,031評(píng)論 0 2
  • 腦子里有什么在抖動(dòng) 于是 狠狠地 把頭掰開 里面空蕩蕩的,一覽無遺 在骨肉的暗處癌椿,竟然有一把劍 正抖落著銹跡 為讓...
    _破格_閱讀 208評(píng)論 0 2
  • 依據(jù)期權(quán)價(jià)值依賴的因素,在無套利市場(chǎng)中踢俄,期權(quán)的價(jià)格有著合理的估值范圍缩功,以無分紅標(biāo)的資產(chǎn)的期權(quán)為例,期權(quán)的價(jià)格應(yīng)該滿...
    腹肌女配角閱讀 573評(píng)論 1 0
  • 書籍:《小強(qiáng)升職記》 作者:鄒鑫 出版社:北京出版社 【Step1】精彩摘錄: 比爾.翁肯(Bill Oncken...
    清小文閱讀 574評(píng)論 0 0