`
xianbin
  • 浏览: 214634 次
  • 来自: ...
社区版块
存档分类
最新评论

利用GSON、自定义注解、反射开发日志记录、显示功能。

阅读更多
环境说明:
JDK 1.5以上,GSon 2.2.2。

阅读对象:
假设读者已经了解Java注解的使用以及如何创建一个指定注解类型,读者对JSON、GSON有基本了解,对Java反射机制有所了解。

需求概述:开发一个日志记录、显示功能,要求当对指定的实体类进行新增、删除、修改操作时,将变化的内容记录到日志表中。

格式要求:
字段中文名:字段值,比如:用户名:张三。

首先新建两个实体类:
package com.gson.tutorial;

import java.util.Date;

public class MySuperEntity {
	private long id;
	private String name;
	private Date date;
	
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
}


package com.gson.tutorial;

import java.util.Date;

import com.google.gson.annotations.Expose;
import com.gson.tutorial.annotation.FieldComment;

public class MyEntity {
	@Expose
	@FieldComment("用户ID")
	private long id;
	@Expose
	@FieldComment("用户名")
	private String userName;
	private String address;
	private Date date;
	private MySuperEntity entity;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public MySuperEntity getEntity() {
		return entity;
	}

	public void setEntity(MySuperEntity entity) {
		this.entity = entity;
	}
}


上面的类中,字段上的@Expose是GSON的注解,表示该字段在进行JSON转换时保留,也就是没有该注解的字段将在进行JSON转换时被忽略。

@FieldComment注解是一个自定义的注解类型,用于填写字段的中文说明,该自定义注解的源码为:
package com.gson.tutorial.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FieldComment {
	String value();
}


下面写一个测试用例:
package com.gson.tutorial;

import java.util.Date;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
		
		MyEntity entity = new MyEntity();
		entity.setId(123456L);
		entity.setUserName("Test User");
		entity.setAddress("金茂中路");
		entity.setDate(new Date());
		
		String json = gson.toJson(entity);
		System.out.println("Using Expose:" + json);
		
		gson = new Gson();
		json = gson.toJson(entity);
		System.out.println("Unusing Expose:" + json);
	}

}


输出结果为:
Using Expose:{"id":123456,"userName":"Test User"}
Unusing Expose:{"id":123456,"userName":"Test User","address":"金茂中路","date":"Sep 23, 2012 11:33:42 PM"}

可以看到,如果使用:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

方式进行JSON转换,那么被@Expose注解的字段将被转成JSON,其他字段将被忽略。而传统的GSON转换方式则不会理会@Expose注解。

接着进行格式转换输出:
package com.gson.tutorial.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.gson.tutorial.MyEntity;

public class Main {
	/**
	 * @param args
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String[] args) throws ClassNotFoundException,
			IllegalAccessException, InvocationTargetException {
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();

		MyEntity entity = new MyEntity();
		entity.setId(123456L);
		entity.setUserName("Test User");
		entity.setAddress("金茂中路");
		entity.setDate(new Date());

		String json = gson.toJson(entity);
		System.out.println("Using Expose:" + json);

		// -------------------------------------
		String className = "com.gson.tutorial.MyEntity";
		Class classDef = Class.forName(className);
		Object logObj = gson.fromJson(json, classDef);
		Field[] fields = classDef.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			boolean isPresent = fields[i]
					.isAnnotationPresent(FieldComment.class);
			if (isPresent) {
				// 取注解中的文字说明
				FieldComment comment = fields[i]
						.getAnnotation(FieldComment.class);
				String fieldComment = comment.value();

				// 取对象中字段的值
				fields[i].setAccessible(true); // 设置为可访问private字段
				Object fieldValue = fields[i].get(logObj);

				String content = String.format("%s:%s", fieldComment,
						fieldValue);
				System.out.println(content);
			}
		}
	}

}


输出结果:
Using Expose:{"id":123456,"userName":"Test User"}
用户ID:123456
用户名:Test User
0
0
分享到:
评论
1 楼 myangle89 2012-09-24  
没实际作用~

要是用注解能解决操作日志的这个功能,实际作用将会非常大~难点在于操作内容可变性,动态性~

相关推荐

    Java基础学习58.pdf

    本文主要探讨Java中的注解(Annotation)及其应用,包括自定义注解、元注解、注解的反射以及一些常见的自定义注解案例。 首先,自定义注解是Java提供的一种元编程方式,它允许程序员在代码中添加元数据。声明一个...

    Java实现操作JSON的便捷工具类完整实例【重写Google的Gson】

    - 能够利用Gson提供的高级特性,比如自定义注解、序列化和反序列化适配器等。 - 理解并能够实现复杂JSON数据结构(如嵌套对象、数组、集合等)的处理。 - 掌握日志记录,能够合理利用日志库记录工具类的行为,方便...

    java_常用jar包整理.rar

    2. **Log4j**: Log4j 是一个广泛使用的日志记录框架,它允许开发者灵活地控制日志信息的输出级别和格式,提高了日志管理和分析的效率。 3. **SLF4J (Simple Logging Facade for Java)**: SLF4J 是一个日志抽象层,...

    Android代码-Square.zip

    8. **Timber**:这是一款日志库,提供了一种更优雅的方式来记录应用程序中的日志信息。Timber提供树形结构的日志组织,支持自定义日志级别和格式,让开发者更便于调试和分析问题。 9. **Okio**:Okio是OkHttp的底层...

    Java utils.zip

    12. **日志记录**:可能会集成常见日志框架如Log4j、SLF4J,提供统一的日志记录接口。 13. **性能优化**:可能包含一些性能优化的工具,如缓存、计时器、内存分析等。 14. **XML/JSON处理**:可能提供了XML或JSON...

    SSM集成应用

    面向切面编程是一种编程范式,用于处理横切关注点,即那些散布在整个应用程序中的、与核心业务逻辑无关的功能(如日志记录、事务管理等)。 **8.2 AOP入门案例_基于AspectJ注解** 通过使用@Aspect、@Before、@...

    springMVC4.1.6版本所有jar包.zip

    9. **拦截器**:Interceptor 可以在请求处理前后执行自定义逻辑,如权限检查、日志记录等。 10. **RESTful 支持**:Spring MVC 支持构建 RESTful 风格的 Web 服务,通过 @PathVariable、@RequestParam 等注解处理 ...

    Retrofit详解

    1. **拦截器(Interceptor)**:通过添加OkHttp拦截器,可以在请求发送前或响应接收后进行自定义操作,如添加全局Header、日志打印等。 2. **缓存策略**:Retrofit结合OkHttp可以实现网络请求的本地缓存,提高用户...

    Conllect-Utils

    9. **日志记录**: - 提供统一的日志接口,便于切换不同的日志实现(如Log4j、SLF4J等)。 - 可能包含了日志级别控制、日志格式化等特性。 10. **网络通信**: - 支持TCP/UDP等网络协议的客户端和服务器端编程,...

    Java笔记word.docx

    - **日志记录**:记录查询失败的信息,以便于后续的排查和调试。 #### 2. MyBatis-Plus单表查询 MyBatis-Plus是一个MyBatis的扩展插件,它简化了常见的CRUD操作。对于单表查询,可以通过编写简单的Lambda表达式...

    common_utils:项目常用工具类

    11. **反射与注解**: - `ReflectionUtils`:动态获取类、字段、方法信息,以及调用方法等。 - `AnnotationUtils`:处理和解析注解。 12. **日志记录**: - `LogUtils`:提供统一的日志打印接口,可以适配不同的...

    LeanAndroid:精益安卓

    进阶内容包括泛型、反射、注解、Lambda表达式以及Java 8及以上版本的新特性。 ### 3. Android SDK 掌握Android SDK的基本组件,如Activity、Intent、BroadcastReceiver、Service和ContentProvider,是Android开发...

    Android设计思想解读开源框架.pdf

    - **原理**:ButterKnife利用注解处理器生成绑定代码,并通过反射机制在运行时绑定视图。 **7.3 Dagger架构设计核心解密** - **Dagger**:是一个依赖注入框架,用于实现控制反转。Dagger2相比Dagger1进行了重构,...

Global site tag (gtag.js) - Google Analytics