在工程中使用JSONVIEW来自定义返回的JSON字段,通过在实体类中配置不同的view来设置不同的返回类型,然后中通过@JsonView
注解来选择相应的返回view,例如:
public class User implements Serializable {
private static final long serialVersionUID = 2158782964550177013L;
public class BaseView{}
public class PublicView extends BaseView{}
public class FullView extends PublicView{}
@JsonView(User.BaseView.class)
private String id = "1";
@JsonView(User.BaseView.class)
private String username = "sunqian";
@JsonView(User.PublicView.class)
private String name = "sunqian";
@JsonView(User.FullView.class)
private String password = "12344321";
@JsonView(User.FullView.class)
private String auth = "administrator";
@JsonView(User.FullView.class)
private String personalId = "320121************";
@JsonView(User.PublicView.class)
private String location = "nanjing";
@JsonView(User.PublicView.class)
private String mobile = "15959595959";
@JsonView(User.FullView.class)
private String degree = "bd";
// 为了方便,直接定义一些默认值,get/set省略
}
@RestController
@CrossOrigin
@RequestMapping("jsonview/")
public class JsonViewTestController {
@RequestMapping(value = "getBaseUserInfo", method = {RequestMethod.GET})
@JsonView(User.BaseView.class)
public Object getBaseUserInfo(){
return new User();
}
@JsonView(User.PublicView.class)
@RequestMapping(value = "getPublicUserInfo", method = {RequestMethod.GET})
public Object getPublicUserInfo(){
return new User();
}
@JsonView(User.FullView.class)
@RequestMapping(value = "getFullUserInfo", method = {RequestMethod.GET})
public Object getFullUserInfo(){
return new User();
}
}
{
"id": "1",
"username": "sunqian"
}
{
"id": "1",
"username": "sunqian",
"name": "sunqian",
"location": "nanjing",
"mobile": "15959595959"
}
{
"id": "1",
"username": "sunqian",
"name": "sunqian",
"password": "12344321",
"auth": "administrator",
"personalId": "320121************",
"location": "nanjing",
"mobile": "15959595959",
"degree": "bd"
}
有时候我们会自定义一些返回结果的格式,比如用于统一返回格式或者是规范对一些异常的捕获,比如在上述的测试代码中加入简单的异常捕获。
public class Result implements Serializable {
private static final long serialVersionUID = -953751321435659670L;
private String status;
private Object body;
public Result() {
}
public Result(String status, Object body) {
this.status = status;
this.body = body;
}
// get/set方法省略
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResultMap {
}
@ResultMap
注解@Aspect
@Component
public class ResultMapping {
@Around("@annotation(com.sunqian.test.entity.ResultMap)")
public Object resultMapping(ProceedingJoinPoint joinPoint){
try {
return new Result("200", joinPoint.proceed());
} catch (Exception ex) {
return new Result("500", ex.getMessage());
} catch (Throwable throwable) {
return new Result("500", throwable.toString());
}
}
}
@RestController
@CrossOrigin
@RequestMapping("jsonview/")
public class JsonViewTestController {
@RequestMapping(value = "getFullUserInfo", method = {RequestMethod.GET})
@ResultMap
public Object getFullUserInfo(){
return new User();
}
}
这时请求上述的接口可以返回以下格式的结果
{
"status": "200",
"body": {
"id": "1",
"username": "sunqian",
"name": "sunqian",
"password": "12344321",
"auth": "administrator",
"personalId": "320121************",
"location": "nanjing",
"mobile": "15959595959",
"degree": "bd"
}
}
在controller中同时加入@JsonView
注解
@RestController
@CrossOrigin
@RequestMapping("jsonview/")
public class JsonViewTestController {
@RequestMapping(value = "getBaseUserInfo", method = {RequestMethod.GET})
@JsonView(User.BaseView.class)
@ResultMap
public Object getBaseUserInfo(){
return new User();
}
@JsonView(User.PublicView.class)
@ResultMap
@RequestMapping(value = "getPublicUserInfo", method = {RequestMethod.GET})
public Object getPublicUserInfo(){
return new User();
}
@JsonView(User.FullView.class)
@RequestMapping(value = "getFullUserInfo", method = {RequestMethod.GET})
@ResultMap
public Object getFullUserInfo(){
return new User();
}
}
这时再请求这3个接口可以看到接口返回了空的对象,很显然这个是错误,经分析可以知道,应该是自定义的切面在处理返回值的时候,与JsonView发生了冲突。
原本想的是JsonView应该也是通过切面的方式来处理结果集的,是不是可以通过设置切面的请求顺序来解决呢?最后尝试了不同的方法,返回的结果都是空的,只能转而通过其他方法来处理了。
通过查看文档了解到,除了使用注解的方式来使用JsonView,还可以通过在自定义的切面的手动调用相关方法来使用。
@Aspect
@Component
public class ResultMapping {
@Autowired
private Gson gson;
@Around("@annotation(com.sunqian.test.entity.ResultMap)")
public Object resultMapping(ProceedingJoinPoint joinPoint){
try {
MethodInvocationProceedingJoinPoint mjp = (MethodInvocationProceedingJoinPoint) joinPoint;
MethodSignature signature = (MethodSignature) mjp.getSignature();
Method method = signature.getMethod();
ResultMap resultMap = method.getAnnotation(ResultMap.class);
ObjectMapper mapper = new ObjectMapper();
return new Result("200", gson.fromJson(mapper.writerWithView(resultMap.view()).writeValueAsString(joinPoint.proceed()), Map.class));
} catch (Exception ex) {
return new Result("500", ex.getMessage());
} catch (Throwable throwable) {
return new Result("500", throwable.toString());
}
}
}
@ResultMap
注解类中定义view属性@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResultMap {
Class view();
}
@RestController
@CrossOrigin
@RequestMapping("jsonview/")
public class JsonViewTestController {
@RequestMapping(value = "getBaseUserInfo", method = {RequestMethod.GET})
@ResultMap(view = User.BaseView.class)
public Object getBaseUserInfo(){
return new User();
}
@ResultMap(view = User.PublicView.class)
@RequestMapping(value = "getPublicUserInfo", method = {RequestMethod.GET})
public Object getPublicUserInfo(){
return new User();
}
@RequestMapping(value = "getFullUserInfo", method = {RequestMethod.GET})
@ResultMap(view = User.FullView.class)
public Object getFullUserInfo(){
return new User();
}
}
这时,再请求这3个接口,可以得到:
{
"status": "200",
"body": {
"id": "1",
"username": "sunqian"
}
}
{
"status": "200",
"body": {
"id": "1",
"username": "sunqian",
"name": "sunqian",
"location": "nanjing",
"mobile": "15959595959"
}
}
{
"status": "200",
"body": {
"id": "1",
"username": "sunqian",
"name": "sunqian",
"password": "12344321",
"auth": "administrator",
"personalId": "320121************",
"location": "nanjing",
"mobile": "15959595959",
"degree": "bd"
}
}
在上述的示意代码中我只在自定义注解中加入了接收JsonView的view参数,事实上在实际的开发中可能还需要加入其他的参数,比如参数返回值的类型,包括对object,array等不同类型的处理,示意代码中只对object类型作了处理