Spring会话尝试使用会话范围序列化服务

时间:2017-02-18 16:39:52

标签: spring spring-mvc session spring-boot aop

我有服务

@Service
@Scope(value = SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyService {
    public void method() throws MyException {
        throw new MyException();
    }
}

和休息控制器:

@RestController
public class MyController {

    @Autowired
    private MyService myService;

    @RequestMapping(value = "/do", method = RequestMethod.POST)
    public String do() {
        myService.method();
        return null;
    }

    @ExceptionHandler(MyException.class)
    public ResponseEntity<MyException> exceptionHandler(MyException e) {
        return new ResponseEntity<MyException>(e, HttpStatus.UNAUTHORIZED);
    }
}

配置文件:

@EnableRedisHttpSession
public class AppConfig {
}

当我请求执行控制器的方法时,服务抛出MyExceptionExceptionHandler抓住它。但是在exceptionHandler返回后,我有一个异常:

org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [my.example.MyService$$EnhancerBySpringCGLIB$$442fa3ef_5]
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:92) ~[spring-data-redis-1.8.0.RELEASE.jar:na]
    at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:171) ~[spring-data-redis-1.8.0.RELEASE.jar:na]
    at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129) ~[spring-data-redis-1.8.0.RELEASE.jar:na]
    at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86) ~[spring-data-redis-1.8.0.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217) ~[spring-session-1.3.0.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170) ~[spring-session-1.3.0.RELEASE.jar:na]
    ...
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [my.example.MyService$$EnhancerBySpringCGLIB$$442fa3ef_5]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:90) ~[spring-data-redis-1.8.0.RELEASE.jar:na]
    ... 33 common frames omitted
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [my.example.MyService$$EnhancerBySpringCGLIB$$442fa3ef_5]
    at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 35 common frames omitted

在调试时,我已经尝试将Myservice对象序列化为键"sessionAttr:scopedTarget.myService"

我不想制作MyService类Serializeble。还有其他解决方案吗?

1 个答案:

答案 0 :(得分:2)

你的bean应该是可序列化的,如下所示:

@Service
@Scope(value = SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyService implements Serializable {
    public void method() throws MyException {
        throw new MyException();
    }
}

原因是使用redis你的bean必须准备好被序列化

  1. 豆子在网络中旅行到redis
  2. bean已在redis数据存储中序列化
  3. 可能你应该想到不要使用redis作为会话存储,事实上我相信你需要为每个会话提供一个新的bean实例,并且为此,集中式会话数据存储可能无效,这是一种经典的方法对这位老板来说可能更好。

    我希望这种反思对你理解为什么我认为你应该考虑一个anoder解决方案是有用的。