方案一:
//手机号 if(StringUtils.isEmpty(user.getMobile())){ return Result.fail("添加用户时,手机号不能为空"); } //角色 if(CollectionUtils.isEmpty(user.getRoles())) { return Result.fail("添加用户时,角色信息不能为空"); }
方案二:
1、实体类注解添加
/*
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束 (字符串) 是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查(集合)约束元素是否为NULL或者是EMPTY.
********上面导入的是两个包******
*/
@NotBlank(message = "应用名称不能为空")
private String applicationName;
2、controller入口处理
@ApiOperation(value="添加API分类接口", notes="添加API分类接口") @PostMapping(value={"/saveCategory"}) public R saveCategory(@RequestHeader String userCode,@Valid @RequestBody ApiCategoryRequest request){ log.info("APICategoryController-->saveCategory添加API分类操作"); return this.apiCategoryService.saveCategory(request,userCode); }
3、自定义返回
package com.dnt.config;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.baomidou.mybatisplus.extension.api.R;
import com.dnt.web.ResultCode;
import com.dnt.web.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.ResponseUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebMvc
@Slf4j
public class WebMvcConfig implements WebMvcConfigurer {
//tomcat下没有 此设置
@Value("${spring.profiles.active}")
private String env;//当前激活的配置文件
@Value("${dnt.feishui.notice.url}")
private String feishuUrl;
/**
* 请求参数的转换
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
WebMvcConfigurer.super.configureMessageConverters(converters);
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
//自定义fastjson配置
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(
SerializerFeature.WriteNullNumberAsZero, // 将数值类型字段的空值输出为0
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.DisableCircularReferenceDetect, // 禁用循环引用
SerializerFeature.IgnoreNonFieldGetter //忽略为空的属性向前台返回
);
fastJsonHttpMessageConverter.setFastJsonConfig(config);
// 添加支持的MediaTypes;不添加时默认为*/*,也就是默认支持全部
// 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes为application/json
// 参考它的做法, fastjson也只添加application/json的MediaType
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(fastJsonHttpMessageConverter);
// 添加 StringHttpMessageConverter,解决中文乱码问题
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
converters.add(stringHttpMessageConverter);
//Long类型的数据转字符串
FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fjc = new FastJsonConfig();
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
serializeConfig.put(Long.class , ToStringSerializer.instance);
serializeConfig.put(Long.TYPE , ToStringSerializer.instance);
fjc.setSerializeConfig(serializeConfig);
fastJsonConverter.setFastJsonConfig(fjc);
converters.add(fastJsonConverter);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
//跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
//设置允许访问的ip与域名信息
registry.addMapping("/**").allowCredentials(true)
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(3600);
}
//统一异常处理
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(new HandlerExceptionResolver() {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
R r = new R();
String message="";
if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
message = e.getMessage();
r.setCode(ResultCode.FAIL.code()).setMsg(message);
log.info(message);
} else if (e instanceof NoHandlerFoundException) {
message = "接口 [" + request.getRequestURI() + "] 不存在";
r.setCode(ResultCode.NOT_FOUND.code()).setMsg(message);
} else if (e instanceof ServletException) {
message = e.getMessage();
r.setCode(ResultCode.FAIL.code()).setMsg(message);
} else if (e instanceof MethodArgumentNotValidException) {
List<FieldError> fieldErrorList = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
if(fieldErrorList.size()>0){
FieldError fieldError = fieldErrorList.get(fieldErrorList.size() - 1);
message=fieldError.getDefaultMessage();
}
r.setCode(ResultCode.FAIL.code()).setMsg(message);
} else {
message = "接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员";
r.setCode(ResultCode.INTERNAL_SERVER_ERROR.code()).setMsg(message);
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
request.getRequestURI(),
handlerMethod.getBean().getClass().getName(),
handlerMethod.getMethod().getName(),
e.getMessage());
} else {
message = e.getMessage();
}
log.error(message, e);
}
responseResult(response, r);
//发送告警通知
sendFeiShu(message);
return new ModelAndView();
}
});
}
private String makeBindErrors(List<FieldError> fieldErrorList, Exception exception) {
String errorMessage = "";
if (CollectionUtil.isEmpty(fieldErrorList)) {
return errorMessage;
}
Object data = null;
int errorCode = 0;
for (FieldError fieldError : fieldErrorList) {
if (fieldError != null) {
//fieldError.getDefaultMessage() 这个就是你自己定义的message
errorMessage = fieldError.getDefaultMessage();
data = fieldError.getRejectedValue();
if (fieldError.getCode().matches("^[-\\\\+]?[\\\\d]*$")) {
errorCode = Integer.parseInt(fieldError.getCode());
} else {
errorCode = 1;
}
break;
}
}
return errorMessage;
}
//发送告警通知
//{"msg_type":"text","content":{"text":"测试通知"}}
private void sendFeiShu(String message) {
JSONObject mes = new JSONObject();
mes.put("text",message);
JSONObject mesj = new JSONObject();
mesj.put("msg_type","text");
mesj.put("content",mes);
/* //发送消息
String str = HttpUtil.post(feishuUrl,mesj);
log.info("消息推送结果:{}",str);*/
String str1 = HttpRequest.post(feishuUrl)
.header(Header.CONTENT_TYPE,"application/json")
.body(mesj.toJSONString())
.execute().body();
log.info("消息推送结果:{}",str1);
}
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
if (!"dev".equals(env)) { //开发环境忽略签名认证
registry.addInterceptor(new HandlerInterceptorAdapter() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//验证签名
boolean pass = validateSign(request);
if (pass) {
return true;
} else {
log.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}",
request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
R r = new R();
r.setCode(ResultCode.UNAUTHORIZED.code()).setMsg("签名认证失败");
responseResult(response, r);
return false;
}
}
});
}
}
private void responseResult(HttpServletResponse response, R result) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setStatus(200);
try {
response.getWriter().write(JSON.toJSONString(result));
} catch (IOException ex) {
log.error(ex.getMessage());
}
}
/**
* 一个简单的签名认证,规则:
* 1. 将请求参数按ascii码排序
* 2. 拼接为a=value&b=value...这样的字符串(不包含sign)
* 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
*/
private boolean validateSign(HttpServletRequest request) {
String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
if (StringUtils.isEmpty(requestSign)) {
return false;
}
List<String> keys = new ArrayList<>(request.getParameterMap().keySet());
keys.remove("sign");//排除sign参数
Collections.sort(keys);//排序
StringBuilder sb = new StringBuilder();
for (String key : keys) {
sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
}
String linkString = sb.toString();
linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'
String secret = "dntApiServer";//密钥,自己修改
String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5
return StringUtils.equals(sign, requestSign);//比较
}
private String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 如果是多级代理,那么取第一个ip为客户端ip
if (ip != null && ip.indexOf(",") != -1) {
ip = ip.substring(0, ip.indexOf(",")).trim();
}
return ip;
}
}