如何让Javamelody使用不同的端口(Spring Boot+暴露的两个HTTP端口)
Posted
技术标签:
【中文标题】如何让Javamelody使用不同的端口(Spring Boot+暴露的两个HTTP端口)【英文标题】:How to make Javamelody use different port (Spring Boot+two HTTP ports exposed) 【发布时间】:2017-04-29 23:06:12 【问题描述】:我有 Spring Boot Web 应用程序。它在端口 8080 上公开 REST API。它还使用 Spring Boot 管理端点 (http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html) 公开管理端口 8081。
我没有任何自定义 Tomcat 配置来实现这一点。我的application.properties
文件中只有属性management.port=8081
。
我已按照中所述配置了 JavaMelody
https://github.com/javamelody/javamelody/wiki/UserGuideAdvanced#spring-boot-app
(我有我的自定义JavaMelodyConfiguration
类,其中org.springframework.boot.web.servlet.FilterRegistrationBean
注册net.bull.javamelody.MonitoringFilter
)。
@Bean
public FilterRegistrationBean javaMelody()
final FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(new MonitoringFilter());
javaMelody.setAsyncSupported(true);
javaMelody.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
javaMelody.addUrlPatterns("/*");
return javaMelody;
通过这种配置,Javamelody 暴露在 8080 端口(业务端口)上。我想把它移到 8081(管理端口)。怎么改?
我使用 Spring Boot 1.4.2.RELEASE,javamelody 1.62.0
【问题讨论】:
在你的项目中搜索 8080,看看你是否找到将其更改为 8081 的地方。 这不会解决我的问题。我仍然希望我的应用在 8080 端口上公开业务 REST api,在 8081 上公开管理 API,在 8081 上公开 javamelody。 【参考方案1】:编辑:此答案仍然正确,但请参阅已接受的答案以获得更简单的解决方案。
EmbeddedTomcatConfiguration.java
package ...
import java.util.ArrayList;
import java.util.List;
import org.apache.catalina.connector.Connector;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmbeddedTomcatConfiguration
@Value("$server.additionalPorts")
private String additionalPorts;
@Bean
public EmbeddedServletContainerFactory servletContainer()
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector[] additionalConnectors = this.additionalConnector();
if (additionalConnectors != null && additionalConnectors.length > 0)
tomcat.addAdditionalTomcatConnectors(additionalConnectors);
return tomcat;
private Connector[] additionalConnector()
if (StringUtils.isBlank(this.additionalPorts))
return null;
String[] ports = this.additionalPorts.split(",");
List<Connector> result = new ArrayList<>();
for (String port : ports)
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(Integer.valueOf(port));
result.add(connector);
return result.toArray(new Connector[] );
application.yml
server:
port: $appPort:8800
additionalPorts: 8880,8881
Application.java
@SpringBootApplication
@ComponentScan(...)
@Import(EmbeddedTomcatConfiguration.class)
public Application
public static void main(String[] args)
SpringApplication.run(Application .class, args);
我对限制从特定端口访问 javamelody 的建议是扩展 javamelody 过滤器,如果请求来自特定端口,则只链接请求,否则返回 404。
来自日志:
INFO TomcatEmbeddedServletContainer:185 - Tomcat started on port(s): 8800 (http) 8880 (http) 8881 (http)
顺便说一句,这种方法会在这些端口上公开其他端点。 为了解决这个问题并将 javamelody 过滤器(/monitoring)限制到特定端口,您需要编写一个过滤器来验证从允许端口请求的路径(servlet 和过滤器路径),记住这些过滤器的顺序很重要。
基于这个答案和我在回答这个问题时已经获得的部分源代码,我在http://tech.asimio.net/2016/12/15/Configuring-Tomcat-to-Listen-on-Multiple-ports-using-Spring-Boot.html发布了一篇关于这个主题的博客文章
【讨论】:
谢谢!使用这样的配置,当我按照描述注册 javamelody 时(我已经编辑了我的问题以包含它),net.bull.javamelody.MonitoringFilter 是否会注册到两个端口? Yw,假设您想使用管理端口和管理上下文路径访问 Javamelody UI,我会尝试将 Javamelody 过滤器映射到 /admin/monitoring 我的意思是 server.servlet-path 设置为 /,management.context-path 设置为 /admin【参考方案2】:如果目标是从 java melody 版本 1.76 开始公开对管理端口的监控现在要简单得多。
您需要 Spring Boot 2.x、执行器以及 yml 或属性文件:
management.server.port:您的自定义端口 management.endpoints.web.exposure.include:你通常想要什么,监控 javamelody.management-endpoint-monitoring-enabled: true在此处查看更多详细信息: https://github.com/javamelody/javamelody/wiki/SpringBootStarter#configuration-in-case-of-management-port
【讨论】:
【参考方案3】:您可以通过 MvcEndpoint 使用 ReportServlet。像这样的:
import net.bull.javamelody.MonitoringFilter;
import net.bull.javamelody.ReportServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* We configure the Java Melody @link MonitoringFilter normally, but disables all access to the UI. Instead,
* we create a @link ReportServlet, and expose it through a @link MvcEndpoint in @link #javaMelodyReportEndpoint().
*/
@Configuration
public class JavaMelodyConfiguration
private final ServletConfig servletConfig;
@Autowired
public JavaMelodyConfiguration(ServletConfig servletConfig)
this.servletConfig = servletConfig;
@Bean
MvcEndpoint javaMelodyReportEndpoint()
ReportServlet reportServlet = new ReportServlet();
// We initialize the servlet with the servlet configuration from the server that runs on server.port, as
// it currently only uses it to access the Collector instance, and some system information.
reportServlet.init(servletConfig);
return new MvcEndpoint()
@Override
public String getPath()
return "/monitoring";
@Override
public boolean isSensitive()
return false;
@Override
public Class<? extends Endpoint> getEndpointType()
return null;
@GetMapping
public void report(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException
reportServlet.service(httpRequest, httpResponse);
;
@Bean
FilterRegistrationBean javaMelodyFilterRegistration()
FilterRegistrationBean javaMelody = new FilterRegistrationBean();
javaMelody.setFilter(monitoringFilter());
javaMelody.setName("javamelody");
return javaMelody;
@Bean
MonitoringFilter monitoringFilter()
return new MonitoringFilter()
@Override
protected boolean isAllowed(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException
// We allow no access to the report (/monitoring) from this filter, access is done through the
// MvcEndpoint above, using the management port.
return false;
;
(我也在这里发布了这个:https://github.com/javamelody/javamelody/issues/601)
【讨论】:
以上是关于如何让Javamelody使用不同的端口(Spring Boot+暴露的两个HTTP端口)的主要内容,如果未能解决你的问题,请参考以下文章
如何配置 JavaMelody 以监控 C3p0 数据源中的 Jdbc 连接