SpringCloud_Admin

依赖pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.pingruan</groupId>
		<artifactId>vander-framework-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>org.pingruan.springboot</groupId>
	<artifactId>vander-springboot-admin</artifactId>
	<name>监控基于 Spring Boot 的应用</name>
	<description>Spring Boot Admin 提供了很多功能,如显示 name、id 和 version,显示在线状态,Loggers 的日志级别管理,Threads 线程管理,Environment 管理等</description>
	<repositories>
		<repository>
			<id>central</id>
			<name>Central Repository</name>
			<url>https://repo.maven.apache.org/maven2</url>
			<layout>default</layout>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	<dependencies>
		<!-- 注册中心服务down发送邮件 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
		</dependency>
		<!-- 服务监控 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-server</artifactId>
			<version>2.0.1</version>
		</dependency>
		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-server-ui</artifactId>
			<version>2.0.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<exclusions>
				<exclusion>
					<groupId>com.netflix.hystrix</groupId>
					<artifactId>hystrix-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

配置文件bootstrap.yml

server:
  port: 9007
spring:
  application:
    name: vander-springboot-admin
  profiles:
    active:
      - security  # 
#-----------------注册中心服务down发送邮件--------------------
  mail: 
    host: smtp.qq.com
    username: 761421218@qq.com
    password: cgdyxuyuqebebbec
    properties:
      mail.debug: false
      mail.smtp.auth: true   #安全认证(默认是true)
      mail.smtp.port: 465
      mail.smtp.ssl.enable: true  #开启ssl加密 否则项目启动时报530error
      mail.smtp.ssl.socketFactory: sf
      mail.smtp.starttls.enable: true
      mail.smtp.starttls.required: true
  boot:
    admin:
      notify:
        mail:
          to: pingruan_vander@163.com    
          from: 761421218@qq.com
#-----------------基本配置(客户端也需要配置)--------------------
management: 
  endpoints: 
    web:
      exposure:
        include:
        - "*"
  endpoint:
    health: 
      show-details: always
#------------注册中心配置------------------
eureka:
  client:
    registerWithEureka: true #服务注册开关
    fetchRegistry: true #服务发现开关
    serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址,多个中间用逗号分隔
      defaultZone: http://root:qwe123@server1:9001/eureka/
  instance:
    prefer-ip-address: true  #将自己的ip地址注册到Eureka服务中
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port} #指定实例id
  
#------------不做安全校验------------------    
---
spring:
  profiles: default

#------------安全校验------------------ 
---
spring:
  profiles: security
  security:
    user:
      name: root
      password: 123
eureka: 
  instance: 
    metadata-map:
      user.name: ${spring.security.user.name} # 配置访问权限(如果客户端配置安全访问,需要配置其对应安全信息)
      user.password: ${spring.security.user.password} #

配置源码

/**
 * springboot应用监控中心
 * 
 * 1、被监控服务需要添加actuator依赖 2、服务注册到euraka 3、服务启动访问/actuator/health status 为 up
 * 4、参考该项目配置文件application.yml 中客户端配置项
 * 
 * 
 * @author vander
 *
 */
@EnableDiscoveryClient
@SpringBootApplication
@EnableAdminServer
public class SpringBootAdmin {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootAdmin.class, args);
	}

	@Profile("default")
	@Configuration
	public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.authorizeRequests().anyRequest().permitAll()//
					.and().csrf().disable();
		}
	}

	/**
	 * 基于安全认证的spring boot admin
	 * 
	 * @author vander
	 *
	 */
	@Profile("security")
	@Configuration
	public static class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
		private final String adminContextPath;

		public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
			this.adminContextPath = adminServerProperties.getContextPath();
		}

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
			successHandler.setTargetUrlParameter("redirectTo");
			successHandler.setDefaultTargetUrl(adminContextPath + "/#/applications");
			http.authorizeRequests()
					.antMatchers(adminContextPath + "/login").permitAll().anyRequest().authenticated().and().formLogin()
					.loginPage(adminContextPath + "/login").successHandler(successHandler).and().logout()
					.logoutUrl(adminContextPath + "/logout").and().csrf().disable();
			// 允许登录页面和静态资源的请求
			http.authorizeRequests().antMatchers("/login.html", "/**/*.css", "/img/**", "/third-party/**").permitAll();
			http.httpBasic();
		}
	}
}
<think>我们讨论的是Java枚举在JSON序列化时的行为。具体来说,当一个枚举作为bean的属性时,在序列化为JSON时,会使用枚举的哪个部分(value还是name)? 默认情况下,常见的JSON库(如Jackson、Gson)会使用枚举的name()方法(即枚举常量的名称)进行序列化。例如,对于`UserType.LOCAL_ADMIN`,默认序列化为字符串`"LOCAL_ADMIN"`。 但是,问题中的枚举定义了两个字段:`value`和`name`。那么,如果我们希望序列化时使用枚举的`value`字段或者`name`字段,我们需要自定义序列化规则。 下面分别以Jackson和Gson为例,展示如何自定义枚举的序列化行为。 ### 1. 默认行为(不自定义) 如果不做任何配置,序列化时使用枚举的常量名(即`name()`方法返回的字符串)。 示例代码(使用Jackson): ```java public class User { private String username; private UserType userType; // 构造方法、getter和setter省略 } // 测试 User user = new User("Alice", UserType.LOCAL_ADMIN); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); ``` 输出结果: ```json {"username":"Alice","userType":"LOCAL_ADMIN"} ``` ### 2. 自定义序列化为枚举的`value`或`name`字段 如果我们希望使用枚举的某个字段(如`value`或`name`)进行序列化,我们可以通过以下方式实现。 #### 使用Jackson 有两种方式: a. 在枚举类上使用`@JsonValue`注解,标注一个方法。这个方法返回的值将作为序列化的值。 b. 在全局配置中设置。 这里我们使用`@JsonValue`注解。 例如,如果我们想序列化枚举的`value`字段: ```java public enum UserType { // ... 枚举常量 private int value; private String name; UserType(int value, String name) { this.value = value; this.name = name; } // 使用@JsonValue注解,表示序列化时使用这个方法的返回值 @JsonValue public int getValue() { return value; } } ``` 那么,`UserType.LOCAL_ADMIN`序列化后将是数字`0`。 如果我们想序列化枚举的`name`字段(注意不是枚举常量名,而是我们自定义的name字段): ```java @JsonValue public String getName() { return name; } ``` 那么,`UserType.LOCAL_ADMIN`序列化后将是字符串`"local_admin"`。 #### 使用Gson 在Gson中,我们需要通过自定义序列化器来实现。 例如,自定义序列化器,使用枚举的`value`字段: ```java public class UserTypeSerializer implements JsonSerializer<UserType> { @Override public JsonElement serialize(UserType userType, Type type, JsonSerializationContext context) { return new JsonPrimitive(userType.getValue()); } } ``` 然后注册这个序列化器: ```java Gson gson = new GsonBuilder() .registerTypeAdapter(UserType.class, new UserTypeSerializer()) .create(); ``` 同样,如果要序列化`name`字段,只需在序列化器中返回`userType.getName()`。 ### 3. 反序列化问题 当我们自定义序列化行为时,通常也需要考虑反序列化。例如,如果我们用`@JsonValue`标记了`getValue()`,那么反序列化时,JSON输入应该是一个整数,然后我们需要将这个整数转换成对应的枚举常量。 在Jackson中,我们可以使用`@JsonCreator`注解来指定一个静态工厂方法: ```java public enum UserType { // ... 枚举常量 @JsonCreator public static UserType fromValue(int value) { for (UserType type : values()) { if (type.value == value) { return type; } } throw new IllegalArgumentException("Invalid value: " + value); } } ``` 在Gson中,同样需要自定义反序列化器。 ### 总结 - 默认情况下,JSON序列化使用枚举的常量名(即`LOCAL_ADMIN`这种形式)。 - 如果想使用枚举的某个字段(如`value`或`name`),需要自定义序列化规则。 - 在Jackson中,可以通过`@JsonValue`注解指定序列化的字段,同时配合`@JsonCreator`实现反序列化。 - 在Gson中,需要自定义`JsonSerializer`和`JsonDeserializer`。 因此,回答你的问题:默认情况下,序列化时既不会取`value`也不会取`name`,而是取枚举常量名。只有通过自定义(使用注解或配置)后,才会取你指定的字段。 ### 示例代码(完整Jackson示例) ```java import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.ObjectMapper; public class EnumSerializationExample { public enum UserType { LOCAL_ADMIN(0, "local_admin"), LOCAL_USER(1, "local_user"), // ... 其他枚举常量 private final int value; private final String name; UserType(int value, String name) { this.value = value; this.name = name; } @JsonValue public int getValue() { return value; } @JsonCreator public static UserType fromValue(int value) { for (UserType type : UserType.values()) { if (type.value == value) { return type; } } throw new IllegalArgumentException("Unknown value: " + value); } } public static class User { private String username; private UserType userType; // 省略构造方法和getter/setter public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public UserType getUserType() { return userType; } public void setUserType(UserType userType) { this.userType = userType; } } public static void main(String[] args) throws Exception { User user = new User(); user.setUsername("Alice"); user.setUserType(UserType.LOCAL_ADMIN); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); System.out.println("Serialized JSON: " + json); // 反序列化 String inputJson = "{\"username\":\"Bob\",\"userType\":1}"; User readUser = mapper.readValue(inputJson, User.class); System.out.println("Deserialized UserType: " + readUser.getUserType()); } } ``` 输出: ``` Serialized JSON: {"username":"Alice","userType":0} Deserialized UserType: LOCAL_USER ``` 注意:在这个例子中,序列化时使用了`value`(整数),反序列化时也根据整数找到对应的枚举。 §§相关问题§§: 1. 如何在Jackson中配置全局的枚举序列化策略(使用toString()方法而不是name())? 2. 使用Gson时,如何在不修改枚举类的情况下自定义枚举的序列化和反序列化? 3. 在Spring Boot中如何全局配置Jackson的枚举序列化行为? 4. 枚举序列化时,使用数字(ordinal)有什么风险?如何避免?</think>### JSON序列化中枚举的处理机制 在Java中,当枚举被JSON序列化时,默认行为取决于使用的JSON库。对于您提供的`UserType`枚举,序列化结果会根据配置不同而有所差异: #### 1. **默认行为(无特殊配置)** - 大多数JSON库(如Jackson、Gson)默认使用枚举的**常量名称**(即`LOCAL_ADMIN`等) - 不会使用自定义的`value`或`name`字段 - 序列化结果示例: ```json {"userType": "LOCAL_ADMIN"} ``` #### 2. **自定义序列化行为** 通过配置,可以控制序列化结果使用`value`或`name`字段: ##### 方案1:使用Jackson的`@JsonValue`注解(推荐) ```java public enum UserType { // ...枚举常量定义... @JsonValue // 关键注解:指定序列化时使用的字段 public int getValue() { return value; } // 或者使用name字段 // @JsonValue // public String getName() { // return name; // } } ``` **序列化结果**: ```json {"userType": 0} // 使用value字段的值 ``` ##### 方案2:Gson的自定义序列化器 ```java public class UserTypeSerializer implements JsonSerializer<UserType> { @Override public JsonElement serialize(UserType src, Type type, JsonSerializationContext context) { // 选择序列化value或name return new JsonPrimitive(src.getValue()); // 或 return new JsonPrimitive(src.getName()); } } // 注册序列化器 Gson gson = new GsonBuilder() .registerTypeAdapter(UserType.class, new UserTypeSerializer()) .create(); ``` #### 3. **完整示例代码** ```java import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.ObjectMapper; public class EnumSerializationDemo { public enum UserType { LOCAL_ADMIN(0, "local_admin"), LOCAL_USER(1, "local_user"); private final int value; private final String name; UserType(int value, String name) { this.value = value; this.name = name; } @JsonValue // 控制序列化使用value字段 public int getValue() { return value; } } public static class UserBean { private String username; private UserType userType; // 构造方法和getter/setter public UserBean(String username, UserType userType) { this.username = username; this.userType = userType; } public String getUsername() { return username; } public UserType getUserType() { return userType; } } public static void main(String[] args) throws Exception { UserBean user = new UserBean("john_doe", UserType.LOCAL_ADMIN); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); System.out.println("Serialized JSON: " + json); } } ``` **输出结果**: ```json {"username":"john_doe","userType":0} ``` ### 关键结论 1. **默认行为**: - 使用枚举常量名称(如`"LOCAL_ADMIN"`) - 忽略自定义的`value`和`name`字段 2. **自定义控制**: - 使用`@JsonValue`注解指定序列化的字段 - 需要显式选择使用`value`还是`name`字段 - 不同JSON库需要不同配置(Jackson/Gson等) 3. **最佳实践**: - 明确指定序列化行为,避免依赖默认实现 - 在枚举类内部使用`@JsonValue`保持封装性 - 考虑添加`@JsonCreator`实现反序列化支持
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值