shiro登陆、共享session、权限,redisTemplate

 

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
**************************************** 登陆拦截 ****************************************
登陆过后才不被拦截
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) throws IOException {
        ShiroFilterFactoryBean factory = new ShiroFilterFactoryBean();
        factory.setSecurityManager(securityManager);
        factory.setLoginUrl("/unauthorizedxmh");
        factory.setUnauthorizedUrl("/forbidden");
        Map<String, String> filterMap =  new LinkedHashMap();
//        OrderedProperties properties = new OrderedProperties("classpath:shiro.properties");
//        filterMap.putAll(Maps.fromProperties(properties));
        filterMap.put("/login","anon");
//        filterMap.put("/**","authc,user");
        filterMap.put("/**","authc");
        factory.setFilterChainDefinitionMap(filterMap);
        Map<String, Filter> filters = factory.getFilters();
        filters.put("authc",new UserLoginFilter());
        return factory;
    }
 
/**
 * 自定义shiro登录过滤器,判断是ajax请求返回json,否则重定向页面
 */
public class UserLoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        if(!isAjaxRequest(WebUtils.toHttp(request))){
            return super.onAccessDenied(request, response);
        }else{
            HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
            //这里是个坑,如果不设置的接受的访问源,那么前端都会报跨域错误,因为这里还没到corsConfig里面
            httpServletResponse.setHeader("Access-Control-Allow-Origin", ((HttpServletRequest) request).getHeader("Origin"));
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json");
 
            JSONObject object = new JSONObject();
            object.put("code",400);
            object.put("msg","登录超时,请重新登录");
            object.put("timestamp",System.currentTimeMillis());
            PrintWriter writer = httpServletResponse.getWriter();
            writer.println(object.toJSONString());
            writer.flush();
            writer.close();
            //todo
            return false;
        }
    }
 
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (request instanceof HttpServletRequest) {
            if ("OPTIONS".equals(((HttpServletRequest) request).getMethod().toUpperCase())) {
                return true;
            }
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }
     
    /**
     * 是否是Ajax请求
     *
     * @param request
     * @return
     */
    private static boolean isAjaxRequest(HttpServletRequest request) {
        String requestedWith = request.getHeader("x-requested-with");
        if (requestedWith != null && "XMLHttpRequest".equalsIgnoreCase(requestedWith)) {
            return true;
        } else {
            return false;
        }
    }
}
 
****************************************  权限拦截 ****************************************
无权访问报异常 org.apache.shiro.authz.UnauthorizedException
第一种写法
    @RequestMapping("/hello1")
    @ResponseBody
    @RequiresPermissions("xmh.test.permission")//必须先login
    public String hello1() {
 
        System.out.println("***************hello1");
 
        return "hello111:";
    }
第二种写法
     boolean b1 = SecurityUtils.getSubject().isPermitted("xxxx");
     boolean b2 = SecurityUtils.getSubject().isPermitted("xmh.test.permission");
     System.out.println(b1+" "+b2);
public class AuthorizeRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        principals.getPrimaryPrincipal();
        // 添加用户权限
        info.addStringPermission("xmh.test.permission");
        System.out.println("AuthorizationInfo:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        //https://blog.csdn.net/wwwffy/article/details/78188973
        return info;
}
/**
     * 开启shiro aop注解支持,使用代理方式; 所以需要开启代码支持; Controller才能使用@RequiresPermissions
     *
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
 
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
 
扩展知识
@ControllerAdvice
public class AdviceController { 异常处理函数

  

 

 

 

 

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
UsernamePasswordToken authenticationToken = new UsernamePasswordToken();
authenticationToken.setUsername(userId);
authenticationToken.setPassword("001".toCharArray());
currentUser.login(authenticationToken);//登录时触发doGetAuthenticationInfo登录校验
 
@Bean
public AuthorizeRealm authorizeRealm(){
return  new AuthorizeRealm();
}
@Bean
public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {//AuthorizingRealm realm, SessionManager sessionManager
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(authorizeRealm());
//        manager.setCacheManager(new RedisCacheManager());
manager.setSessionManager(sessionManager);
return manager;
}
public class AuthorizeRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        principals.getPrimaryPrincipal();
        // 添加用户权限
        info.addStringPermission("user");
        System.out.println("AuthorizationInfo:****************");
        //https://blog.csdn.net/wwwffy/article/details/78188973
        return info;
    }
 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;
        String userName = usernamePasswordToken.getUsername();
        System.out.println("AuthorizeRealm****************userName:"+userName);
 
        StringBuilder sb = new StringBuilder(100);
        for (int i = 0; i < usernamePasswordToken.getPassword().length; i++) {
            sb.append(usernamePasswordToken.getPassword()[i]);
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, sb.toString(), getName());
        return simpleAuthenticationInfo;
//        return null;//登录失败
    }
}

 redis哨兵

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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
分布式集群,共享session
http://localhost:9990/hello3?userId=1qaz21111
http://localhost:9990/hello1 获取相同userId
http://localhost:9999/hello1 获取相同userId
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.1</version>
</dependency>
 
    @Autowired
    private RedisTemplate<Serializable, Serializable> redisTemplate;
    @RequestMapping("/hello3")
    @ResponseBody
    public ResultVo hello3(String userId) {
    ResultVo resultVo = new ResultVo();
        System.out.println("TestController2*****************************:userId:"+userId);
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        session.setAttribute("userId",userId);
        System.out.println("sessionId:"+session.getId());
        resultVo.setMessage((String)session.getId());
        return resultVo;
    }
 
    @RequestMapping("/hello1")
    @ResponseBody
    public String hello1() {
        System.out.println("hello1");
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        String userId = (String) session.getAttribute("userId");
        System.out.println("sessionId:"+session.getId()+",userId:"+userId);
        return "hello:"+session.getId()+","+userId;
    }
 
1,在创建Subject的时候还没有用户信息,只有当subject.login(token)的时候会获取用户信息,才能将用户信息放入session中
2,Shiro对于ThreadLocal<T>的使用方式是将其封装为对自定义的ThreadContext的调用。关于ThreadContext,其显式绑定的就两个实例:Subject和SecurityManager 。这个观察其定义的bind方法就知晓了
3, 但若是容器不存在session,那么Shiro会提供内置的企业级session来管理。当然在开发中,也可以使⽤SessionDAO允许
数据源持久化Session。 
 
@Configuration
//@ConditionalOnBean(Realm.class)
public class ShiroConfig {
    @Bean
    public Cookie cookie() {
        SimpleCookie cookie = new SimpleCookie("OTC-SESSIONID");
        cookie.setSecure(false);
        cookie.setHttpOnly(true);
        cookie.setPath("/");
        cookie.setMaxAge(86400);
//        cookie.setMaxAge(-1);
        return cookie;
    }
    @Bean
    public SessionListener sessionListener() {
        return new SessionListener();
    }
    @Bean
    public SessionDAO sessionDao() {//Realm realm
        RedisSessionDAO dao = new RedisSessionDAO();
//        realm.setSessionDAO(dao);//其他模块使用
        return dao;
    }
    @Bean
    public SessionManager sessionManager(SessionDAO sessionDao, SessionListener sessionListener, Cookie cookie) {//
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(86400000L);
        sessionManager.setSessionDAO(sessionDao);
        sessionManager.getSessionListeners().add(sessionListener);
        sessionManager.setSessionIdCookie(cookie);
        return sessionManager;
    }
    @Bean
    public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {//AuthorizingRealm realm, SessionManager sessionManager
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//        manager.setRealm(realm);
//        manager.setCacheManager(new RedisCacheManager());
        manager.setSessionManager(sessionManager);
        return manager;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) throws IOException {
        ShiroFilterFactoryBean factory = new ShiroFilterFactoryBean();
        factory.setSecurityManager(securityManager);
//        factory.setLoginUrl("/unauthorized");
//        factory.setUnauthorizedUrl("/forbidden");
//        Map<String, String> filterMap = InstanceUtil.newLinkedHashMap();
//        OrderedProperties properties = new OrderedProperties("classpath:config/shiro.properties");
//        filterMap.putAll(Maps.fromProperties(properties));
//        factory.setFilterChainDefinitionMap(filterMap);
//        Map<String, Filter> filters = factory.getFilters();
//        filters.put("authc",new UserLoginFilter());
        return factory;
    }
}
 
public class RedisSessionDAO extends AbstractSessionDAO {
    private static final int EXPIRE_TIME = 600;
    @Autowired
    private RedisTemplate<Serializable, Serializable> redisTemplate;
    private final static Logger logger = LogManager.getLogger();
    public void delete(Serializable sessionId) {
        if (sessionId != null) {
            byte[] sessionKey = buildRedisSessionKey(sessionId);
            RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
            RedisConnection conn = null;
            try {
                conn = RedisConnectionUtils.getConnection(factory);
                conn.del(sessionKey);
            } finally {
                RedisConnectionUtils.releaseConnection(conn, factory);
            }
        }
    }<br>
    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        saveSession(session);
        return sessionId;
    }
 
    @Override
    protected Session doReadSession(Serializable sessionId) {
        byte[] sessionKey = buildRedisSessionKey(sessionId);
        RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
        RedisConnection conn = null;
        try {
            conn = RedisConnectionUtils.getConnection(factory);
            byte[] value = conn.get(sessionKey);
            if (value == null) {
                return null;
            }
            Session session = SerializeUtil.deserialize(value, SimpleSession.class);
            return session;
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
    }
 
    @Override
    public void update(Session session) throws UnknownSessionException {
        saveSession(session);
    }
 
    @Override
    public void delete(Session session) {
        if (session != null) {
            Serializable id = session.getId();
            if (id != null) {
                RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
                RedisConnection conn = null;
                try {
                    conn = RedisConnectionUtils.getConnection(factory);
                    conn.del(buildRedisSessionKey(id));
                } finally {
                    RedisConnectionUtils.releaseConnection(conn, factory);
                }
            }
        }
    }
 
    @Override
    public Collection<Session> getActiveSessions() {
//        List<Session> list = InstanceUtil.newArrayList();
        List<Session> list = new ArrayList<>();
                RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
        RedisConnection conn = null;
        try {
            conn = RedisConnectionUtils.getConnection(factory);
            Set<byte[]> set = conn.keys((Constants.REDIS_SHIRO_SESSION + "*").getBytes());
            for (byte[] key : set) {
                list.add(SerializeUtil.deserialize(conn.get(key), SimpleSession.class));
            }
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
        return list;
    }
 
    private void saveSession(Session session) {
        if (session == null || session.getId() == null) {
            throw new UnknownSessionException("session is empty");
        }
        byte[] sessionKey = buildRedisSessionKey(session.getId());
//        int sessionTimeOut = PropertiesUtil.getInt("session.maxInactiveInterval", getExpireTime());
        int sessionTimeOut =86400;
        byte[] value = SerializeUtil.serialize(session);
        RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
        RedisConnection conn = null;
        try {
            conn = RedisConnectionUtils.getConnection(factory);
            conn.set(sessionKey, value, Expiration.seconds(sessionTimeOut), SetOption.UPSERT);
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
    }
 
    protected int getExpireTime() {
        return EXPIRE_TIME;
    }
 
    private byte[] buildRedisSessionKey(Serializable sessionId) {
        return (Constants.REDIS_SHIRO_SESSION + sessionId).getBytes();
    }
}
 
public class SessionListener implements org.apache.shiro.session.SessionListener {
    private Logger logger = LogManager.getLogger();
    @Autowired
    RedisTemplate redisTemplate;
 
    /* (non-Javadoc)
     * @see org.apache.shiro.session.SessionListener#onStart(org.apache.shiro.session.Session) */
    @Override
    public void onStart(Session session) {
        session.setAttribute(Constants.WEBTHEME, "default");
        logger.info("创建了一个Session连接:[" + session.getId() + "]");
        redisTemplate.opsForSet().add(Constants.ALLUSER_NUMBER, session.getId());
    }
 
    /* (non-Javadoc)
     * @see org.apache.shiro.session.SessionListener#onStop(org.apache.shiro.session.Session) */
    @Override
    public void onStop(Session session) {
        if (getAllUserNumber() > 0) {
            logger.info("销毁了一个Session连接:[" + session.getId() + "]");
        }
        session.removeAttribute(Constants.CURRENT_USER);
        redisTemplate.opsForSet().remove(Constants.ALLUSER_NUMBER, session.getId());
    }
 
    /* (non-Javadoc)
     * @see org.apache.shiro.session.SessionListener#onExpiration(org.apache.shiro.session.Session) */
    @Override
    public void onExpiration(Session session) {
        onStop(session);
    }
 
    /** 获取在线用户数量 */
    public Integer getAllUserNumber() {
        return redisTemplate.opsForSet().size(Constants.ALLUSER_NUMBER).intValue();
    }
}
 
@Configuration
public class RedisConfig {
//    @Bean
//    public GenericObjectPoolConfig redisPoolConfig() {
//        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
//        poolConfig.setMinIdle(PropertiesUtil.getInt("redis.minIdle"));
//        poolConfig.setMaxIdle(PropertiesUtil.getInt("redis.maxIdle"));
//        poolConfig.setMaxTotal(PropertiesUtil.getInt("redis.maxTotal"));
//        poolConfig.setMaxWaitMillis(PropertiesUtil.getInt("redis.maxWaitMillis"));
//        return poolConfig;
//    }
//
//    @Bean(destroyMethod = "shutdown")
//    @ConditionalOnMissingBean(ClientResources.class)
//    public ClientResources clientResources() {
//        return DefaultClientResources.create();
//    }
 
    /**
     * 连接redis的工厂类
     *
     * @return
     */
    @Bean(name = "redisConnectionFactory")
    public RedisConnectionFactory redisConnectionFactory() {//GenericObjectPoolConfig redisPoolConfig, ClientResources clientResources
        LettuceConnectionFactory connectionFactory;
//        String nodes = PropertiesUtil.getString("spring.redis.cluster.nodes");
//        String master = PropertiesUtil.getString("redis.master");
//        String sentinels = PropertiesUtil.getString("redis.sentinels");
//        Duration commandTimeout = Duration.ofMillis(PropertiesUtil.getInt("redis.commandTimeout", 60000));
//        Duration shutdownTimeout = Duration.ofMillis(PropertiesUtil.getInt("redis.shutdownTimeout", 5000));
//        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder()
//                .poolConfig(redisPoolConfig).commandTimeout(commandTimeout).shutdownTimeout(shutdownTimeout)
//                .clientResources(clientResources);
//        LettuceClientConfiguration clientConfiguration = builder.build();
        RedisPassword password = RedisPassword.of("123");
//        String host = PropertiesUtil.getString("redis.host", "localhost");
//        Integer port = PropertiesUtil.getInt("redis.port", 6379);
//        Integer database = PropertiesUtil.getInt("redis.database", 0);
//        if (DataUtil.isNotEmpty(nodes)) {
//            List<String> list = InstanceUtil.newArrayList(nodes.split(","));
//            RedisClusterConfiguration configuration = new RedisClusterConfiguration(list);
//            configuration.setMaxRedirects(PropertiesUtil.getInt("redis.cluster.max-redirects"));
//            configuration.setPassword(password);
//            connectionFactory = new LettuceConnectionFactory(configuration, clientConfiguration);
//        } else if (DataUtil.isNotEmpty(master) && DataUtil.isNotEmpty(sentinels)) {
//            Set<String> set = InstanceUtil.newHashSet(sentinels.split(","));
//            RedisSentinelConfiguration configuration = new RedisSentinelConfiguration(master, set);
//            configuration.setPassword(password);
//            connectionFactory = new LettuceConnectionFactory(configuration, clientConfiguration);
//        } else {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
            configuration.setPassword(password);
            configuration.setHostName("192.168.89.128");
            configuration.setPort(6379);
            configuration.setDatabase(0);
            connectionFactory = new LettuceConnectionFactory(configuration); AbstractRedisClient s;
//        }
        return connectionFactory;
    }
 
    @Bean(name = "redisTemplate")
    public RedisTemplate<Serializable, Serializable> redisTemplate() {//<String, Object>
//StringRedisTemplate的构造方法中默认设置了stringSerializer
        RedisTemplate<Serializable, Serializable> template = new RedisTemplate<>();
//设置开启事务
        template.setEnableTransactionSupport(true);
//set key serializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        GenericFastJsonRedisSerializer valueSerializer = new GenericFastJsonRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(valueSerializer);
        template.setConnectionFactory(redisConnectionFactory());
        template.afterPropertiesSet();
        return template;
    }
}
 
public final class SerializeUtil {
    private SerializeUtil() {
    }
 
    private static final Logger logger = LogManager.getLogger();
    /**
     * 序列化
     *
     * @param object
     * @return
     */
    public static final byte[] serialize(Object object) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            return baos.toByteArray();
        } catch (IOException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        } finally {
            try {
                if (oos != null) {
                    oos.close();
                }
            } catch (Exception e) {
                logger.error("", e);
            }
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (Exception e) {
                logger.error("", e);
            }
        }
    }
 
    /**
     * 反序列化
     *
     * @param bytes
     * @return
     */
    public static final Object deserialize(byte[] bytes) {
        return deserialize(bytes, Object.class);
    }
 
    /**
     * 反序列化
     *
     * @param bytes
     * @return
     */
    @SuppressWarnings("unchecked")
    public static final <K> K deserialize(byte[] bytes, Class<K> cls) {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(bais);
            return (K)ois.readObject();
        } catch (IOException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (Exception e) {
                logger.error("", e);
            }
            try {
                if (bais != null) {
                    bais.close();
                }
            } catch (Exception e) {
                logger.error("", e);
            }
        }
    }
}

  

 

posted @   XUMT111  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示