Привет, в моей предыдущей статье я объяснил, как настроить сервер JMX через Spring и как защитить доступ к нему через аутентификацию и авторизацию.
В этой статье я покажу, как реализовать простой MBean, который позволяет пользователям изменять уровень регистратора Log4j во время выполнения без необходимости перезапуска приложения.
Конфигурация Spring немного изменилась по сравнению с моей предыдущей статьей для облегчения тестирования; вещество остается тем же.
Конфигурация Spring
|
01
02
03
04
05
06
07
08
09
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
|
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jemos-jmx.properties</value> <value>file:///${user.home}/.secure/jmxconnector-credentials.properties</value> </list> </property> </bean><!-- In order to automatically detect MBeans we need to recognise Spring beans --> <context:component-scan base-package="uk.co.jemos.experiments.jmx.mbeans" /><!-- This causes MBeans annotations to be recognised and MBeans to be registered with the JMX server --> <context:mbean-export default-domain="jemos.mbeans"/> <bean id="jemosJmxServer" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="rmiRegistry"> <property name="objectName" value="connector:name=rmi" /> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:${jemos.jmx.rmi.port}/jemosJmxConnector" /> <property name="environment"> <!-- the following is only valid when the sun jmx implementation is used --> <map> <entry key="jmx.remote.x.password.file" value="${user.home}/.secure/jmxremote.password" /> <entry key="jmx.remote.x.access.file" value="${user.home}/.secure/jmxremote.access" /> </map> </property> </bean> <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port" value="${jemos.jmx.rmi.port}" /> </bean><!-- Used for testing --> <bean id="clientConnector" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean" depends-on="jemosJmxServer"> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:${jemos.jmx.rmi.port}/jemosJmxConnector"/> <property name="environment"> <map> <entry key="jmx.remote.credentials"> <bean factory-method="commaDelimitedListToStringArray"> <constructor-arg value="${jmx.username},${jmx.password}" /> </bean> </entry> </map> </property> </bean> </beans> |
Единственная часть конфигурации, которая нас интересует, — это сканирование компонентов Spring и объявление экспортера MBean (что приводит к тому, что аннотации MBean также распознаются и бины Spring регистрируются на сервере JMX как MBeans)
LoggerConfigurator MBean
|
01
02
03
04
05
06
07
08
09
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
|
package uk.co.jemos.experiments.jmx.mbeans;import org.apache.log4j.Level;import org.apache.log4j.Logger;import org.springframework.jmx.export.annotation.ManagedOperation;import org.springframework.jmx.export.annotation.ManagedOperationParameter;import org.springframework.jmx.export.annotation.ManagedOperationParameters;import org.springframework.jmx.export.annotation.ManagedResource;import org.springframework.stereotype.Component;/** * MBean which allows clients to change or retrieve the logging level for a * Log4j Logger at runtime. * * @author mtedone * */@Component@ManagedResource(objectName = LoggerConfigurator.MBEAN_NAME, //description = "Allows clients to set the Log4j Logger level at runtime")public class LoggerConfigurator { public static final String MBEAN_NAME = "jemos.mbeans:type=config,name=LoggingConfiguration"; @ManagedOperation(description = "Returns the Logger LEVEL for the given logger name") @ManagedOperationParameters({ @ManagedOperationParameter(description = "The Logger Name", name = "loggerName"), }) public String getLoggerLevel(String loggerName) { Logger logger = Logger.getLogger(loggerName); Level loggerLevel = logger.getLevel(); return loggerLevel == null ? "The logger " + loggerName + " has not level" : loggerLevel.toString(); } @ManagedOperation(description = "Set Logger Level") @ManagedOperationParameters({ @ManagedOperationParameter(description = "The Logger Name", name = "loggerName"), @ManagedOperationParameter(description = "The Level to which the Logger must be set", name = "loggerLevel") }) public void setLoggerLevel(String loggerName, String loggerLevel) { Logger thisLogger = Logger.getLogger(this.getClass()); thisLogger.setLevel(Level.INFO); Logger logger = Logger.getLogger(loggerName); logger.setLevel(Level.toLevel(loggerLevel, Level.INFO)); thisLogger.info("Set logger " + loggerName + " to level " + logger.getLevel()); }} |
Помимо аннотаций Spring JMX (выделено жирным шрифтом), это обычный бин Spring. Однако с этими аннотациями мы сделали MBean, и этот компонент будет зарегистрирован на сервере JMX при запуске.
Аннотации @ManagedOperation и @ManagedOperationParameters определяют, что будет отображаться в jconsole. Можно было бы опустить эти аннотации, но имена параметров не стали бы чем-то вроде p1 и p2, не давая никакой информации о типе параметра.
Вызов функции, скажем, со значением foo.bar.baz, INFO приведет к следующему выводу:
|
1
2
3
|
...snip2011-08-11 21:33:36 LoggerConfigurator [INFO] Set logger foo.bar.baz to level INFO |
В моей следующей и последней статье для этой серии я покажу, как настроить MBean, который оповещает слушателя о достижении порога памяти HEAP, как объяснялось в одной из моих предыдущих статей.
Продолжайте к части 3 .
Ссылка: JMX и Spring — часть 2 от нашего партнера по JCG
