1. 防止重复提交拦截器
package cn.javabs.framework.interceptor; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import com.alibaba.fastjson2.JSON; import cn.javabs.common.annotation.RepeatSubmit; import cn.javabs.common.core.pojo.ResultCode; import cn.javabs.common.utils.ServletUtils; /** * 防止重复提交拦截器 * * @author Mryang */ @Component public abstract class RepeatSubmitInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); // 自定义注解防止表单重复提交 {间隔时间(5000ms),小于此时间视为重复提交} RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); if (annotation != null) { // 验证是否重复提交由子类实现具体的防重复提交的规则 if (this.isRepeatSubmit(request, annotation)) { // 返回错误消息 ResultCode resultCode = ResultCode.error(annotation.message()); // 将字符串渲染到客户端 ServletUtils.renderString(response, JSON.toJSONString(resultCode)); return false; } } return true; } else { return true; } } /** * 验证是否重复提交由子类实现具体的防重复提交的规则 * * @param request * @return * @throws Exception */ public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); }
2. 全局异常处理器
package cn.javabs.framework.web.exception; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import cn.javabs.common.constant.HttpStatus; import cn.javabs.common.core.pojo.ResultCode; import cn.javabs.common.exception.DemoModeException; import cn.javabs.common.exception.ServiceException; import cn.javabs.common.utils.StringUtils; /** * 全局异常处理器 * * @author Mryang */ @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 权限校验异常 */ @ExceptionHandler(AccessDeniedException.class) public ResultCode handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage()); return ResultCode.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权"); } /** * 请求方式不支持 */ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ResultCode handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); return ResultCode.error(e.getMessage()); } /** * 业务异常 */ @ExceptionHandler(ServiceException.class) public ResultCode handleServiceException(ServiceException e, HttpServletRequest request) { log.error(e.getMessage(), e); Integer code = e.getCode(); return StringUtils.isNotNull(code) ? ResultCode.error(code, e.getMessage()) : ResultCode.error(e.getMessage()); } /** * 拦截未知的运行时异常 */ @ExceptionHandler(RuntimeException.class) public ResultCode handleRuntimeException(RuntimeException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生未知异常.", requestURI, e); return ResultCode.error(e.getMessage()); } /** * 系统异常 */ @ExceptionHandler(Exception.class) public ResultCode handleException(Exception e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生系统异常.", requestURI, e); return ResultCode.error(e.getMessage()); } /** * 自定义验证异常 */ @ExceptionHandler(BindException.class) public ResultCode handleBindException(BindException e) { log.error(e.getMessage(), e); String message = e.getAllErrors().get(0).getDefaultMessage(); return ResultCode.error(message); } /** * 自定义验证异常 */ @ExceptionHandler(MethodArgumentNotValidException.class) public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error(e.getMessage(), e); String message = e.getBindingResult().getFieldError().getDefaultMessage(); return ResultCode.error(message); } /** * 演示模式异常 */ @ExceptionHandler(DemoModeException.class) public ResultCode handleDemoModeException(DemoModeException e) { return ResultCode.error("演示模式,不允许操作"); } }
3.获取IP
package cn.javabs.common.utils.ip; import java.net.InetAddress; import java.net.UnknownHostException; import javax.servlet.http.HttpServletRequest; import cn.javabs.common.utils.StringUtils; /** * 获取IP方法 * * @author Mryang */ public class IpUtils { /** * 获取客户端IP * * @param request 请求对象 * @return IP地址 */ public static String getIpAddr(HttpServletRequest request) { if (request == null) { return "unknown"; } 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("X-Forwarded-For"); } 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("X-Real-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); } /** * 检查是否为内部IP地址 * * @param ip IP地址 * @return 结果 */ public static boolean internalIp(String ip) { byte[] addr = textToNumericFormatV4(ip); return internalIp(addr) || "127.0.0.1".equals(ip); } /** * 检查是否为内部IP地址 * * @param addr byte地址 * @return 结果 */ private static boolean internalIp(byte[] addr) { if (StringUtils.isNull(addr) || addr.length < 2) { return true; } final byte b0 = addr[0]; final byte b1 = addr[1]; // 10.x.x.x/8 final byte SECTION_1 = 0x0A; // 172.16.x.x/12 final byte SECTION_2 = (byte) 0xAC; final byte SECTION_3 = (byte) 0x10; final byte SECTION_4 = (byte) 0x1F; // 192.168.x.x/16 final byte SECTION_5 = (byte) 0xC0; final byte SECTION_6 = (byte) 0xA8; switch (b0) { case SECTION_1: return true; case SECTION_2: if (b1 >= SECTION_3 && b1 <= SECTION_4) { return true; } case SECTION_5: switch (b1) { case SECTION_6: return true; } default: return false; } } /** * 将IPv4地址转换成字节 * * @param text IPv4地址 * @return byte 字节 */ public static byte[] textToNumericFormatV4(String text) { if (text.length() == 0) { return null; } byte[] bytes = new byte[4]; String[] elements = text.split("\\.", -1); try { long l; int i; switch (elements.length) { case 1: l = Long.parseLong(elements[0]); if ((l < 0L) || (l > 4294967295L)) { return null; } bytes[0] = (byte) (int) (l >> 24 & 0xFF); bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); bytes[3] = (byte) (int) (l & 0xFF); break; case 2: l = Integer.parseInt(elements[0]); if ((l < 0L) || (l > 255L)) { return null; } bytes[0] = (byte) (int) (l & 0xFF); l = Integer.parseInt(elements[1]); if ((l < 0L) || (l > 16777215L)) { return null; } bytes[1] = (byte) (int) (l >> 16 & 0xFF); bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); bytes[3] = (byte) (int) (l & 0xFF); break; case 3: for (i = 0; i < 2; ++i) { l = Integer.parseInt(elements[i]); if ((l < 0L) || (l > 255L)) { return null; } bytes[i] = (byte) (int) (l & 0xFF); } l = Integer.parseInt(elements[2]); if ((l < 0L) || (l > 65535L)) { return null; } bytes[2] = (byte) (int) (l >> 8 & 0xFF); bytes[3] = (byte) (int) (l & 0xFF); break; case 4: for (i = 0; i < 4; ++i) { l = Integer.parseInt(elements[i]); if ((l < 0L) || (l > 255L)) { return null; } bytes[i] = (byte) (int) (l & 0xFF); } break; default: return null; } } catch (NumberFormatException e) { return null; } return bytes; } /** * 获取IP地址 * * @return 本地IP地址 */ public static String getHostIp() { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { } return "127.0.0.1"; } /** * 获取主机名 * * @return 本地主机名 */ public static String getHostName() { try { return InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { } return "未知"; } /** * 从多级反向代理中获得第一个非unknown IP地址 * * @param ip 获得的IP地址 * @return 第一个非unknown IP地址 */ public static String getMultistageReverseProxyIp(String ip) { // 多级反向代理检测 if (ip != null && ip.indexOf(",") > 0) { final String[] ips = ip.trim().split(","); for (String subIp : ips) { if (false == isUnknown(subIp)) { ip = subIp; break; } } } return ip; } /** * 检测给定字符串是否为未知,多用于检测HTTP请求相关 * * @param checkString 被检测的字符串 * @return 是否未知 */ public static boolean isUnknown(String checkString) { return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); } }
4 获取地址类
package cn.javabs.common.utils.ip; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import cn.javabs.common.config.JavabsConfig; import cn.javabs.common.constant.Constants; import cn.javabs.common.utils.StringUtils; import cn.javabs.common.utils.http.HttpUtils; /** * 获取地址类 * * @author Mryang */ public class AddressUtils { private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); // IP地址查询 public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; // 未知地址 public static final String UNKNOWN = "XX XX"; public static String getRealAddressByIP(String ip) { // 内网不查询 if (IpUtils.internalIp(ip)) { return "内网IP"; } if (JavabsConfig.isAddressEnabled()) { try { String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); if (StringUtils.isEmpty(rspStr)) { log.error("获取地理位置异常 {}", ip); return UNKNOWN; } JSONObject obj = JSON.parseObject(rspStr); String region = obj.getString("pro"); String city = obj.getString("city"); return String.format("%s %s", region, city); } catch (Exception e) { log.error("获取地理位置异常 {}", ip); } } return UNKNOWN; } }
表现层Controller通用数据处理
package cn.javabs.common.core.controller; import java.beans.PropertyEditorSupport; import java.util.Date; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import cn.javabs.common.constant.HttpStatus; import cn.javabs.common.core.pojo.ResultCode; import cn.javabs.common.core.pojo.model.LoginUser; import cn.javabs.common.core.page.PageDomain; import cn.javabs.common.core.page.TableDataInfo; import cn.javabs.common.core.page.TableSupport; import cn.javabs.common.utils.DateUtils; import cn.javabs.common.utils.PageUtils; import cn.javabs.common.utils.SecurityUtils; import cn.javabs.common.utils.StringUtils; import cn.javabs.common.utils.sql.SqlUtil; /** * 表现层通用数据处理 * * @author Mryang */ public class BaseController { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 将前台传递过来的日期格式的字符串,自动转化为Date类型 */ @InitBinder public void initBinder(WebDataBinder binder) { // Date 类型转换 binder.registerCustomEditor(Date.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(DateUtils.parseDate(text)); } }); } /** * 设置请求分页数据 */ protected void startPage() { PageUtils.startPage(); } /** * 设置请求排序数据 */ protected void startOrderBy() { PageDomain pageDomain = TableSupport.buildPageRequest(); if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) { String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); PageHelper.orderBy(orderBy); } } /** * 清理分页的线程变量 */ protected void clearPage() { PageUtils.clearPage(); } /** * 响应请求分页数据 */ @SuppressWarnings({ "rawtypes", "unchecked" }) protected TableDataInfo getDataTable(List<?> list) { TableDataInfo rspData = new TableDataInfo(); rspData.setCode(HttpStatus.SUCCESS); rspData.setMsg("查询成功"); rspData.setRows(list); rspData.setTotal(new PageInfo(list).getTotal()); return rspData; } /** * 返回成功 */ public ResultCodesuccess() { return ResultCode.success(); } /** * 返回失败消息 */ public ResultCodeerror() { return ResultCode.error(); } /** * 返回成功消息 */ public ResultCode success(String message) { return ResultCode.success(message); } /** * 返回失败消息 */ public ResultCode error(String message) { return ResultCode.error(message); } /** * 响应返回结果 * * @param rows 影响行数 * @return 操作结果 */ protected ResultCode toAjax(int rows) { return rows > 0 ? ResultCode.success() : ResultCode.error(); } /** * 响应返回结果 * * @param result 结果 * @return 操作结果 */ protected ResultCode toAjax(boolean result) { return result ? success() : error(); } /** * 页面跳转 */ public String redirect(String url) { return StringUtils.format("redirect:{}", url); } /** * 获取用户缓存信息 */ public LoginUser getLoginUser() { return SecurityUtils.getLoginUser(); } /** * 获取登录用户id */ public Long getUserId() { return getLoginUser().getUserId(); } /** * 获取登录部门id */ public Long getDeptId() { return getLoginUser().getDeptId(); } /** * 获取登录用户名 */ public String getUsername() { return getLoginUser().getUsername(); } }
分享是快乐的,也见证了个人成长历程,文章大多都是工作经验总结以及平时学习积累,基于自身认知不足之处在所难免,也请大家指正,共同进步。