需求场景: 基于服务治理的原则,公司重构了很多项目,其中使用了dubbo作为服务框架。作为底层的服务存在,由上层的业务系统进行服务的编排。一是为了系统之间的解耦,同时系统之间也能更好的交互。
其他依赖:springboot,JDK8
目前的需求是,上层业务系统在调用底层的服务的时候,底层系统需要记录全部的入参、出参和处理耗时。第二是统一返回格式,不向上抛出异常。最开始打算使用Spring aop 进行切面处理。发现 dubbo 和 aop有冲突,网上的解决方案有两种,一种是更改dubbo底层的源码,二是调整切入逻辑。两种方案都不满意,查询资料,发现dubbo 提供filter 拦截。
代码。。。。。。
返回类
public class ResponseMessage<T> implements Serializable {
public ResponseMessage() {
}
public ResponseMessage(boolean status, String statusCode, String message, T result) {
this.status = status;
this.statusCode = statusCode;
this.message = message;
this.result = result;
}
private boolean status;
private String statusCode;
private String message;
private T result;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
}
业务层返回
public class UserCenterResponse<T> extends ResponseMessage<T>
{
/**
* 意义,目的和功能,以及被用到的地方<br>
*/
private static final long serialVersionUID = -1490267187174046793L;
}
代理类
public interface IUserCenterOperation
{
UserCenterResponse<BaseUser> findUserByid(Long userId);
}
实现
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.zto.webUserCenter_userOpera.dto.UserCenterResponse;
import com.zto.webUserCenter_userOpera.dto.BaseUser;
import com.zto.webUserCenter_userOpera.manager.FindUserById;
import com.zto.webUserCenter_userOpera.service.IUserCenterOperation;
@Service(group = "userCenterOperation", timeout = 1000, version = "1.0",filter="dubboServiceFilter")
public class UserCenterOperation implements IUserCenterOperation
{
@Autowired
private FindUserById findUserById;
@Override
public UserCenterResponse<BaseUser> findUserByid(Long userId)
{
UserCenterResponse<BaseUser> res = null;
res = findUserById.exce(userId);
// 业务实现,可替换
return res;
}
}
filter
@Activate
public class DubboServiceFilter implements Filter
{
private final static Logger logger = LoggerFactory.getLogger(DubboServiceFilter.class);
public Result invoke(Invoker<?> invoker, Invocation invocation)
{
Result result = null;
Long takeTime = 0L;
try
{
Long startTime = System.currentTimeMillis();
result = invoker.invoke(invocation);
if (result.getException() instanceof Exception)
{
throw new Exception(result.getException());
}
takeTime = System.currentTimeMillis() - startTime;
}
catch (Exception e)
{
logger.error("Exception:{},request{},curr error:{},msg:{}", invocation.getClass(),
invocation.getArguments(), e.toString(), ExceptionUtils.getRootCause(e));
result = new RpcResult(ServiceUtils.getResponse(e));
return result;
}
finally
{
logger.info("method:[{}],request:{},response:{},takeTime:{} ms",
invocation.getMethodName(), invocation.getArguments(), JsonUtil.toJSON(result),
takeTime);
}
return result;
}
}
返回值处理类
public class ServiceUtils
{
public static <T> UserCenterResponse<T> getResponse(T t)
{
UserCenterResponse<T> response = new UserCenterResponse<T>();
// 处理自定义异常返回
if (t instanceof UserCenterException)
{
response.setMessage(((UserCenterException)t).getExceptionEnums().getMessage());
response.setStatusCode(((UserCenterException)t).getExceptionEnums().getCode());
response.setStatus(false);
}
// 处理未知异常
else if (t instanceof Exception)
{
response.setMessage(DBExceptionEnums.UNKNOWN_ERROR.getMessage());
response.setStatusCode(DBExceptionEnums.UNKNOWN_ERROR.getCode());
response.setStatus(false);
}
// 正常返回
else
{
response.setStatusCode("200");
response.setStatus(true);
response.setResult(t);
}
return response;
}
}
dubbo 配置文件参考 :https://www.cnblogs.com/Alandre/p/6490142.html
详细 阐述下 关于filter 配置。
在resources中创建文件
- META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
内容:dubboServiceFilter=com.zto.webUserCenter_userOpera.aop.DubboServiceFilter
application.properties 配置 添加
dubbo.provider.filter =dubboServiceFilter
参考资料:
Springboot 整合 Dubbo/ZooKeeper 详解 SOA 案例
被事务代理的spring service 不能使用注解方式发布dubbo服务的问题解决
----------------------------------------------------------------------------------------------------------
代码 还有点乱,有还有优化的空间
dubboServiceFilter |