1. 程式人生 > >spring boot 自定義註解過濾返回欄位

spring boot 自定義註解過濾返回欄位

 在spring boot啟動類加上  (這裡不加貌似也可以生效)

@Import(value = { ApplicationConfig.class })

@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.apih5.mybatis.dao")
@Import(value = { ApplicationConfig.class })
// @EnableCaching // 開啟快取,需要顯示的指定
@EnableApolloConfig
public class Apih5Application {

	private static final Logger logger = LoggerFactory.getLogger(Apih5Application.class);

	public static void main(String[] args) {
		String version = SpringBootVersion.getVersion();
		System.out.println(version);
		String implementationVersion = SpringApplication.class.getPackage().getImplementationVersion();

		System.out.println(implementationVersion);

		System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));
		if (args != null && args.length > 0 && StrUtil.isNotEmpty(args[0])) {
			String path = System.getProperty("user.dir");
			String applicationTest = path + "/src/main/resources/application-test.yml";
			String dbconfig = path + "/src/main/resources/workflow-conf/properties/dbconfig.properties";
			write(applicationTest, read(applicationTest, args[0]));
			write(dbconfig, read(dbconfig, args[0]));

			String targetApplicationTest = path + "/target/classes/application-test.yml";
			String targetDbconfig = path + "/target/classes/workflow-conf/properties/dbconfig.properties";
			write(targetApplicationTest, read(applicationTest, args[0]));
			write(targetDbconfig, read(dbconfig, args[0]));

			// appid
			if (args.length > 1) {
				String appid = path + "/src/main/resources/META-INF/app.properties";
				write(appid, readAppId(appid, args[1]));
			}
		}

		SpringApplication application = new SpringApplication(Apih5Application.class);
		application.setBannerMode(Banner.Mode.OFF);
		application.run(args);
		LoggerUtils.printLogger(logger, "--------------APIH5 啟動完成----------------");
	}

ApplicationConfig類如下:

package com.apih5.framework.components;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//三個註解貌似不加也可以
@Configuration
@ComponentScan(basePackages = { "com.apih5.controller" }, useDefaultFilters = true)
// @ComponentScan(basePackages = { "com.apih5.framework.components" },
// useDefaultFilters = true)
@EnableWebMvc
// public class ApplicationConfig extends WebMvcConfigurerAdapter{//過期類
// public class ApplicationConfig extends WebMvcConfigurationSupport {//不生效
public class ApplicationConfig implements WebMvcConfigurer {// 生效
	@Bean
	public JsonReturnHandler jsonReturnHandler() {
		return new JsonReturnHandler();// 初始化json過濾器
	}

	@Override
	public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
		returnValueHandlers.add(jsonReturnHandler());

	}

	// @Override
	// public void addResourceHandlers(ResourceHandlerRegistry registry) {
	// registry.addResourceHandler("/**").addResourceLocations("/");// 所有
	// }
	//
	// @Override
	// public void configureViewResolvers(ViewResolverRegistry registry) {
	// registry.jsp("/WEB-INF/jsp/", ".jsp");
	// }

}

 JsonReturnHandler類如下:

package com.apih5.framework.components;

import javax.servlet.http.HttpServletResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.apih5.framework.annotation.JsonFieldFilter;
import com.apih5.framework.components.JsonFilterSerializer;

public class JsonReturnHandler implements HandlerMethodReturnValueHandler {
	@Override
	public void handleReturnValue(Object returnObject, MethodParameter paramter, ModelAndViewContainer container,
			NativeWebRequest request) throws Exception {
		container.setRequestHandled(true);
		JsonFilterSerializer serializer = new JsonFilterSerializer();
		if (paramter.hasMethodAnnotation(JsonFieldFilter.class)) {// 如果有JsonFieldFilter註解,則過濾返回的物件returnObject
			JsonFieldFilter jsonFilter = paramter.getMethodAnnotation(JsonFieldFilter.class);
			serializer.filter(jsonFilter.type() == null ? returnObject.getClass() : jsonFilter.type(),
					jsonFilter.include(), jsonFilter.exclude());// 呼叫過濾方法
		}
		HttpServletResponse response = request.getNativeResponse(HttpServletResponse.class);
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().write(serializer.toJson(returnObject));
	}

	@Override
	public boolean supportsReturnType(MethodParameter methodParameter) {
		return methodParameter.hasMethodAnnotation(JsonFieldFilter.class);
	}
}

 JsonFilterSerializer類如下:

package com.apih5.framework.components;

import org.junit.Test;

import com.apih5.framework.entity.Response;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

public class JsonFilterSerializer {
	private static final String DYNC_INCLUDE = "DYNC_INCLUDE";// 包含的標識
	private static final String DYNC_EXCLUDE = "DYNC_EXCLUDE";// 過濾的標識
	private ObjectMapper mapper = new ObjectMapper();

	@JsonFilter(DYNC_EXCLUDE)
	interface DynamicExclude {
	}

	@JsonFilter(DYNC_INCLUDE)
	interface DynamicInclude {
	}

	public void filter(Class<?> clazz, String include, String exclude) {
		if (clazz == null)
			return;
		if (include != null && include.length() > 0) {
			// 包含的操作
			mapper.setFilterProvider(new SimpleFilterProvider().addFilter(DYNC_INCLUDE,
					SimpleBeanPropertyFilter.filterOutAllExcept(include.split(","))));
			// 多個欄位用,分割開
			mapper.addMixIn(clazz, DynamicInclude.class);
		} else if (exclude != null && exclude.length() > 0) {
			mapper.setFilterProvider(new SimpleFilterProvider().addFilter(DYNC_EXCLUDE,
					SimpleBeanPropertyFilter.serializeAllExcept(exclude.split(","))));
			mapper.addMixIn(clazz, DynamicExclude.class);
		}
	}

	public String toJson(Object object) throws JsonProcessingException {
		return mapper.writeValueAsString(object);
	}

	@Test
	public void testFilterJson() throws JsonProcessingException {
		JsonFilterSerializer jsonFilter = new JsonFilterSerializer();
		jsonFilter.filter(Response.class, "failReason", null);
		// Response中有status、failReason、currentIndex三個屬性
		System.out.println(jsonFilter.toJson(new Response("test", "成功", -1)));
	}

}

 自定義註解 JsonFieldFilter如下:


package com.apih5.framework.annotation;

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

/**
 * * 描述: * *
 * 
 * <pre>
 * HISTORY * **************************************************************************** * 
 * ID DATE PERSON REASON * 1 2018年11月22日 cx Create 
 * * **************************************************************************** 
 * *
 * </pre>
 * 
 * * @author cx
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonFieldFilter {
	Class<?> type();// 對哪個類的屬性進行過濾

	String include() default "";// 包含哪些欄位,即哪些欄位可以顯示

	String exclude() default "";// 不包含哪些欄位,即哪些欄位不可以顯示
}

 Junit測試需要類如下:

package com.apih5.framework.entity;

public class Response {
	private String status;
	private String failReason;
	private int currentIndex;

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getFailReason() {
		return failReason;
	}

	public void setFailReason(String failReason) {
		this.failReason = failReason;
	}

	public int getCurrentIndex() {
		return currentIndex;
	}

	public void setCurrentIndex(int currentIndex) {
		this.currentIndex = currentIndex;
	}

	public Response(String status, String failReason, int currentIndex) {
		super();
		this.status = status;
		this.failReason = failReason;
		this.currentIndex = currentIndex;
	}

}

 最後測試controller如下:

 注意點:

 1、用@Controller 替代 @RestController;

 2、在不需要過濾欄位 @JsonFieldFilter(type = ***.class, include = "***")的介面上面使用@ResponseBody註解,但是在需要 過   濾欄位的介面上一定不要用@ResponseBody註解,否則過濾失效。

package com.apih5.controller;

import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

import com.apih5.framework.annotation.JsonFieldFilter;
import com.apih5.framework.annotation.RequireToken;
import com.apih5.framework.entity.ResponseEntity;
import com.apih5.mybatis.pojo.ZxHwGxProcess;
import com.apih5.service.ZxHwGxProcessService;

@Controller
public class ZxHwGxProcessController {

	@Autowired(required = true)
	private ZxHwGxProcessService zxHwGxProcessService;

	@ApiOperation(value = "******", notes = "*****")
	@ApiImplicitParam(name = "zxHwGxProcess", value = "entity", dataType = "ZxHwGxProcess")
	@RequireToken
	// @ResponseBody
	@PostMapping("/countZxHwGxProcessNumByStatus")
	@JsonFieldFilter(type = ZxHwGxProcess.class, include = "rootLevelId,rootLevelName,totalNum")
	public ResponseEntity countZxHwGxProcessNumByStatus(@RequestBody(required = false) ZxHwGxProcess zxHwGxProcess) {
		return zxHwGxProcessService.countZxHwGxProcessNumByStatus(zxHwGxProcess);
	}

}