spring mvc Interceptor 返回json数据
今天在使用springmvc的拦截器做签名校验时需要在拦截器中返回校验失败的提示信息,刚开始因为代码逻辑的问题,一直不能返回json数据,后来才发现直接使用HttpServletResponse就可以返回,再此记录下这个低级错误:
package com.app.ws.card.util;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.app.ws.card.service.CardClientService;
import com.app.ws.card.web.CardControllerFlagInterface;
/**
* 一卡通接口权限检查拦截器
*
* @author wanxing
* @createTime 2017-08-01
*/
public class CardApiInterceptor extends HandlerInterceptorAdapter {
private static Log logger = LogFactory.getLog(CardApiInterceptor.class);
/** 30分钟 */
protected static final long THIRTY_MINU_MSEC = 30 * 60 * 1000;// 半个小时
@Autowired
private CardClientService clientService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Object bean = handlerMethod.getBean();
/**
* 如果不是一卡通的Controller则直接放过
*/
if (!(bean instanceof CardControllerFlagInterface)) {
return true;
}
// 将请求参数转化为map,以便后续校验签名
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> param = new HashMap<String, Object>();
buildParamMap(parameterMap, param);
String appId = (String) param.get("appId");
String timestampStr = (String) param.get("timestamp");
String sign = (String) param.get("sign");
// 校验参数完整性
if (StringUtils.isBlank(appId) || StringUtils.isBlank(timestampStr) || StringUtils.isBlank(sign)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("请求参数不完整[appId:%s][timestamp:%s][sign:%s]", appId, timestampStr, sign));
}
SendMsgUtil.sendJsonMessage(response, CardResult.instance().build(ResultStatus.PARAM_IMPERFECT));
return false;
}
// 校验接口调用是否超时
long timestamp = Long.valueOf(timestampStr);
long currTimestamp = new Date().getTime();
if (currTimestamp - timestamp > THIRTY_MINU_MSEC) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("接口调用超时[%s,%s]",
DateFormatUtils.format(new Date(currTimestamp), "yyyy-MM-dd HH:mm:ss"),
DateFormatUtils.format(new Date(timestamp), "yyyy-MM-dd HH:mm:ss")));
}
SendMsgUtil.sendJsonMessage(response, CardResult.instance().build(ResultStatus.SIGN_OVERTIME));
return false;
}
// 查询appId对应的accessKey
String accessKey = clientService.getAccessKeyByAppId(appId);
if (StringUtils.isBlank(accessKey)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("没有找到[%s]对应的accessKey", appId));
}
SendMsgUtil.sendJsonMessage(response, CardResult.instance().build(ResultStatus.APPID_NOT_FOUND));
return false;
}
// 校验签名
String otherSign = TencentSignUtil.buildSign(param, accessKey);
if (!StringUtils.equals(sign, otherSign)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("用户签名错误[用户签名:%s][服务器生成签名:%s]", sign, otherSign));
}
SendMsgUtil.sendJsonMessage(response, CardResult.instance().build(ResultStatus.SIGN_ERROR));
return false;
}
return true;
}
private void buildParamMap(Map<String, String[]> parameterMap, Map<String, Object> param) {
for (Entry<String, String[]> entry : parameterMap.entrySet()) {
String key = entry.getKey();
String[] value = entry.getValue();
if (!ArrayUtils.isEmpty(value)) {
if (StringUtils.isNotBlank(value[0])) {
param.put(key, value[0]);
}
} else {
continue;
}
}
}
public CardClientService getClientService() {
return clientService;
}
public void setClientService(CardClientService clientService) {
this.clientService = clientService;
}
}
public class SendMsgUtil {
/**
* 发送消息 text/html;charset=utf-8
* @param response
* @param str
* @throws Exception
*/
public static void sendMessage(HttpServletResponse response, String str) throws Exception {
response.setContentType("text/html; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print(str);
writer.close();
response.flushBuffer();
}
/**
* 将某个对象转换成json格式并发送到客户端
* @param response
* @param obj
* @throws Exception
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat));
writer.close();
response.flushBuffer();
}
}