需求說明
- 根據需求部分字段内容為正規表達式,包含特殊符号’<’,’>等,導緻html解析錯誤,字段顯示錯誤或顯示部分。
- 對特殊字段需要過濾,如:使用者密碼等不應該傳回到前端
解決方案
- 可以在單個方法中對資料進行處理,但是這樣會增加代碼複雜度,具有侵入性
- 使用切面思想,對傳回json進行統一處理
代碼
- 建立注解
package com.pactera.ai.manage.commons.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @user : Administrator
* @desc : 處理responseBody 隻能在@ResponseBody 方法上使用
* @date : 2019年2月15日
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@ResponseBody
public @interface SerializedField {
/**
* 需要去除的字段
* @return
*/
String[] excludes() default {};
/**
* 資料是否需要加密
* @return
*/
boolean encode() default false;
/**
* 需要替換特殊字元的字段 特殊字段包括< > 等
* @return
* */
String[] characters() default {};
}
- 建立類實作ResponseBodyAdvice接口,對傳回參數進行處理。ResponseBodyAdvice可以指定參數類型,進而實作對不對傳回類型資料進行不同處理,這裡使用ResponseBodyAdvice對所有類型進行統一處理。
package com.pactera.ai.manage.commons.web;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.pactera.ai.manage.commons.annotation.SerializedField;
import com.pactera.ai.manage.commons.util.LayerData;
import com.pactera.ai.manage.commons.util.RestResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @user : Administrator
*
* @desc : 處理傳回json
*
* @date : 2019年2月15日
*/
@Slf4j
@Order(1)
@ControllerAdvice(basePackages = "com.pactera.ai.manage.controller")
public class CustomResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
// 傳回false 不執行 beforeBodyWrite方法
return methodParameter.getMethod().isAnnotationPresent(SerializedField.class);
}
@SuppressWarnings("unchecked")
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if (body == null)
return null;
SerializedField serializedField = methodParameter.getMethodAnnotation(SerializedField.class);
String [] characters = serializedField.characters();
if (characters != null && characters.length > 0) { //處理特殊字元
Property property =new Property();
property.setCharacters(characters);
if (body instanceof LayerData) {
LayerData<Object> os = (LayerData<Object>) body;
List<Object> data = os.getData();
os.setData(handleList(data,property));
return os;
}else if(body instanceof RestResponse) {
RestResponse restData= (RestResponse) body;
Object object = restData.get("data");
if(object instanceof List) {
restData.setData(handleList((List<Object>) object,property));
}else {
restData.setData(handleSingleObject(object,property));
}
return restData;
}
}
return body;
}
/**
* 處理單個對象
*
* @param object
* @return
*/
private Object handleSingleObject(Object o,Property property) {
try {
Field[] fields = o.getClass().getDeclaredFields();
List<String> characterList = Arrays.asList(property.getCharacters());
for (Field field : fields) {
// 隻處理string類型
if(field.getType()==String.class) {
field.setAccessible(true);
// 有限考慮包含字段
if (characterList.contains(field.getName())) {
String newVal = (String) field.get(o);
if(!StringUtils.isBlank(newVal)) {
newVal = newVal.replaceAll("<", "<").replaceAll(">", ">");
field.set(o, newVal);
}
}
}
}
} catch (Exception e) {
log.error("handleSingleObject", e);
}
return o;
}
/**
* 處理傳回值是清單
*
* @param list
* @return
*/
private List<Object> handleList(List<Object> list,Property property) {
List<Object> retList = new ArrayList<>();
for (Object o : list) {
Object obj = handleSingleObject(o,property);
retList.add(obj);
}
return retList;
}
}
@Data
class Property{
private String [] characters;
}
代碼隻對特殊字元進行處理,字段過濾等功能待開發。
- 在Controller中使用注解
@PostMapping("list")
@SerializedField(characters= {"regex"})
public LayerData<PatPredicatelibsys> list(@RequestParam(value = "page",defaultValue = "1")Integer page,
@RequestParam(value = "limit",defaultValue = "10")Integer limit,String condition){
LayerData<PatPredicatelibsys> resp= new LayerData<>();
...
return resp;
}
傳回頁面處理
以上是傳回json時的處理,如果傳回是頁面時如何處理呢? 系統使用.ftl類型頁面,代碼如下:
$(function(){
<#if pat.regex??>
$("#regex").text("${pat.regex}")
</#if>
});