个别场景中需要前端指定返回字段解决方案。必须一些可以编辑显示列的table,在这讨论几种实现方式。思路如下:
1,后端数据全返回,前端控制显示与否,缺点是增加数据库查询压力(都查出来了),增加流量传输。
2,数据库查询所有字段业务层序列化的时候指定序列化的字段,缺点就是增加数据库查询压力。
3,数据库动态查询,缺点是安全性健壮性不好把控(不可使用预先编译且有sql注入风险)。
仁者见仁智者见智,有没有更优秀,更优雅的方法欢迎谈论。
第一种不用说,后端和往常一样,该怎么样还怎么样。
下面说后两种。
JSON序列化之指定序列化字段(fastjson,gson,jackson)
1,jackson
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;
import org.springframework.util.StringUtils;
/**
* jackson自定义JSON返回字段
*
* @author Mr_Lee
* @date 2020-08-13 08:35
*/
public class JackSonFilter {
private static final String INCLUDE = "JSON_INCLUDE";
private static final String EXCEPT = "JSON_EXCEPT";
@JsonFilter(INCLUDE)
private interface MyJsonInclude {
}
@JsonFilter(EXCEPT)
private interface MyJsonExcept {
}
/**
* 引入字段
*/
public static String mapperInclude(Object bean, String include) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
if (StringUtils.hasText(include)) {
mapper.setFilterProvider(new SimpleFilterProvider().addFilter(INCLUDE,
SimpleBeanPropertyFilter.filterOutAllExcept(include.split(","))));
mapper.addMixIn(bean.getClass(), MyJsonInclude.class);
}
return mapper.writeValueAsString(bean);
}
/**
* 排除字段
*/
public static String mapperExcept(Object bean, String except) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
if (StringUtils.hasText(except)) {
mapper.setFilterProvider(new SimpleFilterProvider().addFilter(EXCEPT,
SimpleBeanPropertyFilter.serializeAllExcept(except.split(","))));
mapper.addMixIn(bean.getClass(), MyJsonExcept.class);
}
return mapper.writeValueAsString(bean);
}
}
2,gson
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.util.StringUtils;
import java.util.Arrays;
/**
* Gson自定义JSON返回字段
*
* @author Mr_Lee
* @date 2020-08-13 10:04
*/
public class GsonFilter {
/**
* 引入字段
*/
public static String toIncludeJson(Object bean, String include) {
ExclusionStrategy myExclusionStrategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fa) {
if (StringUtils.hasText(include)) {
return !Arrays.asList(include.split(",")).contains(fa.getName());
}
return true;
}
@Override
public boolean shouldSkipClass(Class> clazz) {
return false;
}
};
Gson gson = new GsonBuilder().setExclusionStrategies(myExclusionStrategy).create();
return gson.toJson(bean);
}
/**
* 排除字段
*/
public static String toExceptJson(Object bean, String except) {
ExclusionStrategy myExclusionStrategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fa) {
if (StringUtils.hasText(except)) {
return Arrays.asList(except.split(",")).contains(fa.getName());
}
return false;
}
@Override
public boolean shouldSkipClass(Class> clazz) {
return false;
}
};
Gson gson = new GsonBuilder().setExclusionStrategies(myExclusionStrategy).create();
return gson.toJson(bean);
}
}
3,fastjson
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import org.springframework.util.StringUtils;
import java.util.Arrays;
/**
* FastJson自定义JSON返回字段
*
* @author Mr_Lee
* @date 2020-08-13 09:57
*/
public class FastJsonFilter {
/**
* 引入字段
*/
public static String toIncludeJSONString(Object bean, String include) {
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
if (StringUtils.hasText(include)) {
filter.getIncludes().addAll(Arrays.asList(include.split(",")));
}
return JSONObject.toJSONString(bean, filter);
}
/**
* 排除字段
*/
public static String toExceptJSONString(Object bean, String except) {
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
if (StringUtils.hasText(except)) {
filter.getExcludes().addAll(Arrays.asList(except.split(",")));
}
return JSONObject.toJSONString(bean, filter);
}
}
测试
import com.fasterxml.jackson.core.JsonProcessingException;
/**
* @author Mr_Lee
* @date 2020-08-13 08:37
*/
public class TestCase {
public static void main(String[] args) throws JsonProcessingException {
User user = new User(1, "lwc", "123456", true, "[email protected]");
String jackSonString1 = JackSonFilter.mapperInclude(user, "id,userName");
String jackSonString2 = JackSonFilter.mapperExcept(user, "id");
System.out.println(jackSonString1);
System.out.println(jackSonString2);
System.out.println("---------------------------------------------");
String fastJsonString1 = FastJsonFilter.toIncludeJSONString(user, "id,userName");
String fastJsonString2 = FastJsonFilter.toExceptJSONString(user, "id");
System.out.println(fastJsonString1);
System.out.println(fastJsonString2);
System.out.println("---------------------------------------------");
String gsonString1 = GsonFilter.toIncludeJson(user, "id,userName");
String gsonString2 = GsonFilter.toExceptJson(user, "id");
System.out.println(gsonString1);
System.out.println(gsonString2);
}
}
{"id":1,"userName":"lwc"}
{"userName":"lwc","passWord":"123456","status":true,"email":"[email protected]"}
---------------------------------------------
{"id":1,"userName":"lwc"}
{"email":"[email protected]","passWord":"123456","status":true,"userName":"lwc"}
---------------------------------------------
{"id":1,"userName":"lwc"}
{"userName":"lwc","passWord":"123456","status":true,"email":"[email protected]"}
通过上面的方法可以实现方法二。
方法三呢?
可用MyBatis的动态SQL进行数据返回;故可在业务层将指定返回的列传入数据层,利用foreach标签进行遍历返回数据。
1.请求参数
@Data
public class QueryDTO {
/**
* 返回值
*/
private Set targetFields;
}
2.mapper接口
/**
* 查询数据
* @param record
* @return
*/
List query(QueryDTO record);
3.mapper.xml实现
resourceId, platformCount, createUserId
4.注意事项
a.使用动态返回字段时,不可使用预先编译,故foreach中使用‘$’符号,而不使用‘#’;
b.foreach标签后若还有其他固定字段返回,记得用逗号‘,’分隔。