mirror of https://gitee.com/maxjhandsome/pig
增加网关统一异常处理,不在ControllerAOP处理
This commit is contained in:
parent
0c8044860d
commit
85c50241c6
|
@ -26,13 +26,12 @@ public class LogReceiveListener {
|
|||
|
||||
@RabbitHandler
|
||||
public void receive(LogVo logVo) {
|
||||
System.out.println(logVo.getSysLog());
|
||||
SysLog sysLog = logVo.getSysLog();
|
||||
if (StringUtils.isNotEmpty(logVo.getToken())) {
|
||||
String username = UserUtils.getUserName(logVo.getToken());
|
||||
MDC.put(KEY_USER, username);
|
||||
sysLog.setCreateBy(username);
|
||||
sysLogService.insert(sysLog);
|
||||
MDC.remove(KEY_USER);
|
||||
}
|
||||
String username = UserUtils.getUserName(logVo.getToken());
|
||||
MDC.put(KEY_USER, username);
|
||||
sysLog.setCreateBy(username);
|
||||
sysLogService.insert(sysLog);
|
||||
MDC.remove(KEY_USER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class LogController extends BaseController {
|
|||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public R<Boolean> delete(@PathVariable Integer id) {
|
||||
int o = 11 / 0;
|
||||
return new R<>(sysLogService.updateByLogId(id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<result column="params" property="params" />
|
||||
<result column="time" property="time" />
|
||||
<result column="del_flag" property="delFlag" />
|
||||
<result column="exception" property="exception" />
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package com.github.pig.admin.controller;
|
||||
|
||||
import com.github.pig.admin.dto.UserDto;
|
||||
import com.xiaoleilu.hutool.http.HttpUtil;
|
||||
import com.xiaoleilu.hutool.json.JSON;
|
||||
import com.xiaoleilu.hutool.json.JSONUtil;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017/12/25
|
||||
* UserController单元测试
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class UserControllerTest {
|
||||
@Autowired
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserGet() throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1)
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.username").value("admin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAdd() throws Exception {
|
||||
UserDto userDto = new UserDto();
|
||||
userDto.setRole(1);
|
||||
userDto.setNewpassword1("@1312312");
|
||||
mockMvc.perform(MockMvcRequestBuilders.post("/user")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(JSONUtil.toJsonStr(userDto)))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPostEdu() throws Exception {
|
||||
System.out.println(HttpUtil.post("http://eco.ahau.edu.cn/jc/dtrans", MapUtils.EMPTY_MAP));
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import com.github.pig.common.util.UserUtils;
|
|||
import com.github.pig.common.util.exception.CheckException;
|
||||
import com.github.pig.common.util.exception.UnloginException;
|
||||
import com.github.pig.common.vo.UserVo;
|
||||
import com.xiaoleilu.hutool.lang.Console;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
|
@ -102,7 +103,8 @@ public class ControllerAop {
|
|||
result = pjp.proceed();
|
||||
logger.info(pjp.getSignature() + "use time:" + (System.currentTimeMillis() - startTime));
|
||||
} catch (Throwable e) {
|
||||
result = handlerException(pjp, e);
|
||||
logger.error("异常信息:", e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(username)) {
|
||||
UserUtils.clearAllUserInfo();
|
||||
|
@ -111,23 +113,4 @@ public class ControllerAop {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
private R<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
|
||||
R<?> result = new R();
|
||||
|
||||
// 已知异常
|
||||
if (e instanceof CheckException) {
|
||||
result.setMsg(e.getLocalizedMessage());
|
||||
result.setCode(R.FAIL);
|
||||
} else if (e instanceof UnloginException) {
|
||||
result.setMsg("Unlogin");
|
||||
result.setCode(R.NO_LOGIN);
|
||||
} else {
|
||||
logger.error(pjp.getSignature() + " error ", e);
|
||||
result.setMsg(e.toString());
|
||||
result.setCode(R.FAIL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,11 @@ public class SysLog implements Serializable {
|
|||
*/
|
||||
private String delFlag;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String exception;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -173,20 +178,31 @@ public class SysLog implements Serializable {
|
|||
this.delFlag = delFlag;
|
||||
}
|
||||
|
||||
public String getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public void setException(String exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SysLog{" +
|
||||
", id=" + id +
|
||||
", type=" + type +
|
||||
", title=" + title +
|
||||
", createBy=" + createBy +
|
||||
", createDate=" + createTime +
|
||||
"id=" + id +
|
||||
", type='" + type + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", createBy='" + createBy + '\'' +
|
||||
", createTime=" + createTime +
|
||||
", updateTime=" + updateTime +
|
||||
", remoteAddr=" + remoteAddr +
|
||||
", userAgent=" + userAgent +
|
||||
", requestUri=" + requestUri +
|
||||
", method=" + method +
|
||||
", params=" + params +
|
||||
"}";
|
||||
", remoteAddr='" + remoteAddr + '\'' +
|
||||
", userAgent='" + userAgent + '\'' +
|
||||
", requestUri='" + requestUri + '\'' +
|
||||
", method='" + method + '\'' +
|
||||
", params='" + params + '\'' +
|
||||
", time=" + time +
|
||||
", delFlag='" + delFlag + '\'' +
|
||||
", exception='" + exception + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package com.github.pig.common.vo;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017/12/25
|
||||
* spring boot 的异常对象
|
||||
*/
|
||||
public class ErrorPojo implements Serializable {
|
||||
|
||||
@JSONField(name = "timestamp")
|
||||
private long timestamp;
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
@JSONField(name = "error")
|
||||
private String error;
|
||||
@JSONField(name = "exception")
|
||||
private String exception;
|
||||
@JSONField(name = "message")
|
||||
private String message;
|
||||
@JSONField(name = "path")
|
||||
private String path;
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public void setException(String exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
|
@ -2,23 +2,27 @@ package com.github.pig.gateway.filter;
|
|||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017/11/20
|
||||
* 在RateLimitPreFilter 之前执行,不然又空指针问题
|
||||
*/
|
||||
@Component
|
||||
public class AccessFilter extends ZuulFilter {
|
||||
|
||||
@Override
|
||||
public String filterType() {
|
||||
return "pre";
|
||||
return FilterConstants.PRE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int filterOrder() {
|
||||
return 0;
|
||||
return FORM_BODY_WRAPPER_FILTER_ORDER - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.github.pig.gateway.filter;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pig.common.util.R;
|
||||
import com.github.pig.gateway.service.LogSendService;
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ERROR_TYPE;
|
||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2017-12-25 17:53:38
|
||||
* 网关统一异常处理
|
||||
*/
|
||||
@Component
|
||||
public class ErrorHandlerFilter extends ZuulFilter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ValidateCodeFilter.class);
|
||||
|
||||
@Autowired
|
||||
private LogSendService logSendService;
|
||||
|
||||
@Override
|
||||
public String filterType() {
|
||||
return ERROR_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int filterOrder() {
|
||||
return SEND_RESPONSE_FILTER_ORDER + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
RequestContext requestContext = RequestContext.getCurrentContext();
|
||||
return requestContext.getThrowable() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
RequestContext requestContext = RequestContext.getCurrentContext();
|
||||
logSendService.send(requestContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,6 @@ import static org.springframework.cloud.netflix.zuul.filters.support.FilterConst
|
|||
*/
|
||||
@Component
|
||||
public class LoggerFilter extends ZuulFilter {
|
||||
private static final String KEY_USER = "user";
|
||||
|
||||
@Autowired
|
||||
private LogSendService logSendService;
|
||||
|
|
|
@ -9,7 +9,8 @@ import com.netflix.zuul.context.RequestContext;
|
|||
public interface LogSendService {
|
||||
/**
|
||||
* 往消息通道发消息
|
||||
* @param requestContext
|
||||
*
|
||||
* @param requestContext requestContext
|
||||
*/
|
||||
void send(RequestContext requestContext);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package com.github.pig.gateway.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pig.common.constant.CommonConstant;
|
||||
import com.github.pig.common.entity.SysLog;
|
||||
import com.github.pig.common.util.UserUtils;
|
||||
import com.github.pig.common.vo.ErrorPojo;
|
||||
import com.github.pig.common.vo.LogVo;
|
||||
import com.github.pig.gateway.service.LogSendService;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.xiaoleilu.hutool.http.HttpUtil;
|
||||
import com.xiaoleilu.hutool.io.IoUtil;
|
||||
import com.xiaoleilu.hutool.util.URLUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.core.AmqpTemplate;
|
||||
|
@ -16,6 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
|
@ -28,12 +36,20 @@ public class LogSendServiceImpl implements LogSendService {
|
|||
@Autowired
|
||||
private AmqpTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* 1. 获取 requestContext 中的请求信息
|
||||
* 2. 如果返回状态不是OK,则获取返回信息中的错误信息
|
||||
* 3. 发送到MQ
|
||||
*
|
||||
* @param requestContext 上下文对象
|
||||
*/
|
||||
@Override
|
||||
public void send(RequestContext requestContext) {
|
||||
HttpServletRequest request = requestContext.getRequest();
|
||||
String requestUri = request.getRequestURI();
|
||||
String method = request.getMethod();
|
||||
SysLog log = new SysLog();
|
||||
log.setType(CommonConstant.STATUS_NORMAL);
|
||||
log.setRemoteAddr(HttpUtil.getClientIP(request));
|
||||
log.setRequestUri(URLUtil.getPath(requestUri));
|
||||
log.setMethod(method);
|
||||
|
@ -42,16 +58,48 @@ public class LogSendServiceImpl implements LogSendService {
|
|||
log.setCreateBy(UserUtils.getUserName(request));
|
||||
Long startTime = (Long) requestContext.get("startTime");
|
||||
log.setTime(System.currentTimeMillis() - startTime);
|
||||
|
||||
//正常发送服务异常解析
|
||||
if (requestContext.getResponseStatusCode() != HttpStatus.SC_OK) {
|
||||
InputStream inputStream = requestContext.getResponseDataStream();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
InputStream stream1 = null;
|
||||
InputStream stream2 = null;
|
||||
byte[] buffer = IoUtil.readBytes(inputStream);
|
||||
try {
|
||||
baos.write(buffer);
|
||||
baos.flush();
|
||||
stream1 = new ByteArrayInputStream(baos.toByteArray());
|
||||
stream2 = new ByteArrayInputStream(baos.toByteArray());
|
||||
String resp = IoUtil.read(stream1, CommonConstant.UTF8);
|
||||
ErrorPojo error = JSONObject.parseObject(resp, ErrorPojo.class);
|
||||
log.setType(CommonConstant.STATUS_LOCK);
|
||||
log.setException(error.getMessage());
|
||||
requestContext.setResponseDataStream(stream2);
|
||||
} catch (IOException e) {
|
||||
logger.error("响应流解析异常:", e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
IoUtil.close(stream1);
|
||||
IoUtil.close(baos);
|
||||
IoUtil.close(inputStream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//网关内部异常
|
||||
Throwable throwable = requestContext.getThrowable();
|
||||
if (throwable != null) {
|
||||
logger.error("网关异常", throwable);
|
||||
log.setException(throwable.getMessage());
|
||||
}
|
||||
|
||||
//保存发往MQ(只保存授权)
|
||||
LogVo logVo = new LogVo();
|
||||
logVo.setSysLog(log);
|
||||
//解析用户名的事情异步到rabbit消费中处理
|
||||
if (StringUtils.isNotEmpty(request.getHeader(CommonConstant.REQ_HEADER))) {
|
||||
logVo.setToken(request.getHeader(CommonConstant.REQ_HEADER));
|
||||
}
|
||||
try {
|
||||
rabbitTemplate.convertAndSend(CommonConstant.LOG_QUEUE, logVo);
|
||||
}catch (Exception e) {
|
||||
logger.error("MQ发送日志异常,异常信息:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue