我有一个使用 Spring Boot 1.4.2 和 CXF JAXRS 的项目设置。我想将弹簧启动执行器添加到项目中。这是我添加到项目中的配置。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
在此之后我创建了一个 WAR 文件,然后将其部署在外部 tomcat 服务器中。但是当我访问健康 URL localhost:8080/management/health 时,它给出 404 HTTP 代码。服务器正常启动,我可以看到包含以下详细信息的日志:
健康配置日志
[localhost-startStop-1] 信息 org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping - 映射“{[/management/health || /management/health.json],products=[application/json]}" 公开 java.lang.Object
Servlet 配置日志
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean - 映射过滤器:'springSecurityFilterChain' 到:[/*]
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.FilterRegistrationBean - 映射 过滤器:“webRequestLoggingFilter”至:[/*]
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.FilterRegistrationBean - 映射 过滤器:“applicationContextIdFilter”至:[/*]
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.ServletRegistrationBean - 映射 servlet:'dispatcherServletRegistration' 到 []
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.ServletRegistrationBean - 映射 servlet:'dispatcherServlet' 到 [/]
[localhost-startStop-1] 信息 org.springframework.boot.web.servlet.ServletRegistrationBean - 映射 servlet:'CXFServlet' 到 [/services/*]
问题已解决,这是详细信息。由于 CXF 和 Spring Boot 一起配置在一起,因此 CXF REST API 和执行器端点都配置为 '/'。为 CXF RESt 端点配置的 servlet bean 的名称是dispatcherServletRegistration。由于 CXf 的引导启动器位于 POM 中,因此还发生了 CXF servlet 的自动配置。因此,您可以找到 CXFServlet 也配置为 /services/*。
将 servlet: 'dispatcherServletRegistration' 映射到 []
将 servlet: 'dispatcherServlet' 映射到 [/]
将 servlet:“CXFServlet”映射到 [/services/*]
我删除了自动配置选项(CXFServlet),因为我需要一些 CXF JAXRS 实现所需的自定义,并将 dispatcherServletRegistration 映射到 /services/*,现在一切正常。现在执行器在 '/' 下工作,CXF REST API 在 /services 下工作。
就我而言,我有 Spring 1.5.X ,我无法对 CXF 和 Spring Actuator 使用两个不同的基本路径。我需要保留“/”作为根应用程序路径,并添加一个 RestEnpoint 来返回执行器运行状况结果。
因此,当 CXF 返回使用 @Autowired + ObjectMapper 在服务层上生成的 Health Info 的字符串结果时,我使用另一种方法。
注意:您应该启用注释上下文支持才能应用此解决方案。
以下解决方法对我有用:
将 CXF Servlet 保留在“/”上
在我的例子中,我使用 Camel + CXF,但是您需要做的就是创建以下组件来构建 Health 对象:
@Component
public class InfoHealthEndpoint extends HealthEndpoint {
@Autowired
private InfoEndpoint infoEndpoint;
public InfoHealthEndpoint(HealthAggregator healthAggregator, Map<String, HealthIndicator> healthIndicators) {
super(healthAggregator, healthIndicators);
}
@Override
public Health invoke() {
Health health = super.invoke();
return new Health.Builder(health.getStatus(), health.getDetails())
.withDetail("info", infoEndpoint.invoke())
.build();
}
}
并创建一个为 CXF 响应控制器返回字符串结果的服务。
@服务 公共课 HealthService {
@Autowired
private InfoHealthEndpoint infoHealthEndpoint;
@Autowired
private ObjectMapper mapper;
private static final String HEALTH_UP = "UP";
public void health(Exchange exchange) throws JsonProcessingException {
Health health = infoHealthEndpoint.invoke();
String healthReponse = mapper.writeValueAsString(infoHealthEndpoint.invoke());
if(!HEALTH_UP.equals(health.getStatus().getCode())){
Response response = Response.status(503).entity(healthReponse).build();
exchange.getOut().setBody(response);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
}else{
exchange.getIn().setBody(healthReponse);
}
}
}
注意:在我的例子中,我使用 Apache Camel (Exchange) 在路由上设置响应,但是此解决方案可以通过使用简单的字符串返回适用于另一种情况。
此答案归功于@Danny:将 Spring Boot Actuator /health 和 /info 合并为一个
它对我有用
@Bean
@Primary
public DispatcherServletPath dispatcherServletPath() {
return () -> "";
}
@Bean
public DispatcherServlet dispatcherServletActuator() {
return new DispatcherServlet();
}
@Bean
public ServletRegistrationBean<CXFServlet> dispatcherServlet() {
ServletRegistrationBean<CXFServlet> cxf = new ServletRegistrationBean<>(new CXFServlet(), "/v1/*");
cxf.setName("cxfServlet");
return cxf;
}