Grails配置management endpoints独立端口后抛出GroovyCastException如何解决
问题根因
当你为Actuator管理端点配置独立的8989端口后,Spring Boot会为管理端点单独启动一个独立的Web容器上下文,该上下文未经过Grails封装,请求持有的属性类型为原生Spring的ServletRequestAttributes。而Grails拦截器中默认注入的request对象会自动强转为Grails自定义的GrailsWebRequest类型,两种类型不兼容,因此抛出类转换异常。
共用8080端口时所有请求都走Grails封装的Web上下文,请求都会被转换为GrailsWebRequest类型,因此不会触发报错。
解决方案
方案1:拦截器放行管理端口请求(推荐)
Actuator端点属于基础设施管理接口,无需执行业务拦截器逻辑,可直接在拦截器中判断请求类型后放行,修改拦截器代码如下:
import org.springframework.web.context.request.RequestContextHolder import org.grails.web.servlet.mvc.GrailsWebRequest class TestInterceptor { TestInterceptor() { matchAll() } boolean before() { // 非GrailsWebRequest的请求均为管理端口的Actuator请求,直接放行 def requestAttrs = RequestContextHolder.getRequestAttributes() if (!(requestAttrs instanceof GrailsWebRequest)) { return true } // 原有业务逻辑 if (request.forwardURI?.endsWith('.json')) { // ... 原有代码 return false } return true } }
方案2:兼容两种请求类型
如果需要拦截器对管理端口的请求也生效,可手动从请求属性中取原生请求对象,不使用Grails注入的request对象:
import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.ServletRequestAttributes import org.grails.web.servlet.mvc.GrailsWebRequest class TestInterceptor { TestInterceptor() { matchAll() } boolean before() { def requestAttrs = RequestContextHolder.getRequestAttributes() String forwardURI = null if (requestAttrs instanceof GrailsWebRequest) { forwardURI = requestAttrs.request.forwardURI } else if (requestAttrs instanceof ServletRequestAttributes) { forwardURI = requestAttrs.request.forwardURI } if (forwardURI?.endsWith('.json')) { // ... 原有代码 return false } return true } }
方案3:取消独立端口配置
如果无强制要求必须使用独立端口暴露Actuator端点,可删除management.server.port配置,改为通过路径区分管理端点,所有请求都会走Grails上下文,不会出现类型兼容问题。
内容的提问来源于stack exchange,提问作者MKB
相关产品推荐
相关产品推荐

