父工程
-
pom文件
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RC1</spring-cloud.version> <mybatis.starter.version>1.3.2</mybatis.starter.version> <mapper.starter.version>2.0.2</mapper.starter.version> <druid.starter.version>1.1.9</druid.starter.version> <mysql.version>5.1.32</mysql.version> <pageHelper.starter.version>1.2.3</pageHelper.starter.version> <leyou.latest.version>1.0.0-SNAPSHOT</leyou.latest.version> <fastDFS.client.version>1.26.1-RELEASE</fastDFS.client.version> </properties> <dependencyManagement> <dependencies> <!-- springCloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- mybatis启动器 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.starter.version}</version> </dependency> <!-- 通用Mapper启动器 --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>${mapper.starter.version}</version> </dependency> <!-- 分页助手启动器 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pageHelper.starter.version}</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--FastDFS客户端--> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>${fastDFS.client.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins>
Eureka服务端
-
pom文件
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.0.1.RELEASE</version> </dependency> </dependencies>
-
主启动器
@SpringBootApplication @EnableEurekaServer public class LyRegistry { public static void main(String[] args) { SpringApplication.run(LyRegistry.class,args); } }
-
yml配置
server: port: 10086 spring: application: name: ly-registry eureka: client: register-with-eureka: false # 是否注册到eureka fetch-registry: true # 是否从eureka中拉取服务列表 service-url: defaultZone: http://127.0.0.1:${server.port}/eureka server: enable-self-preservation: false #关闭自我保护 eviction-interval-timer-in-ms: 5000 # 每隔5秒进行一次服务列表清理 instance: ip-address: 127.0.0.1 instance-id: ${spring.application.name}:${server.port}
Zuul网关端
-
pom文件
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.0.1.RELEASE</version> </dependency> </dependencies>
-
主启动器
@EnableZuulProxy @SpringCloudApplication public class LyGateWay { public static void main(String[] args) { SpringApplication.run(LyGateWay.class); } }
-
yml配置
server: port: 10010 spring: application: name: ly-gateway eureka: client: fetch-registry: true registry-fetch-interval-seconds: 5 service-url: defaultZone: http://127.0.0.1:10086/eureka instance: ip-address: 127.0.0.1 instance-id: ${spring.application.name}:${server.port} zuul: prefix: /api strip-prefix: true # 是否去除前缀,默认为true routes: item-service: /item/** # 将商品微服务映射到/item/** ribbon: ConnectTimeout: 250 # 连接超时时间(ms) ReadTimeout: 2000 # 通信超时时间(ms) OkToRetryOnAllOperations: true # 是否对所有操作重试 MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数 MaxAutoRetries: 1 # 同一实例的重试次数 hystrix: command: default: execution: isolation: thread: timeoutInMillisecond: 10000 # 熔断超时时长:10000ms
item微服务(二级父工程)
-
pom文件(子工程依赖本工程,将自动加入modules)
<modules> <module>ly-item-interface</module> <module>ly-item-service</module> </modules>
item-interface端,父工程为item
-
创建的一个item对象,需要使用lombok插件
-
pom文件
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
-
item对象
@Data//getter、setter对象 @NoArgsConstructor//无参构造 @AllArgsConstructor//有参构造 public class Item implements Serializable{ private Integer id; private String name; private Double price; }
item-service端,父工程为item
-
pom文件
<!--因为是做一个服务端,需要引入eureka客户端、web启动器、mybatis启动器、分页助手、通用mapper、数据库驱动等--> <dependencies> <!--Eureka客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--web启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mybatis启动器--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!-- 通用Mapper启动器 --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>${mapper.starter.version}</version> </dependency> <!-- 分页助手启动器 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pageHelper.starter.version}</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.leyou</groupId> <artifactId>ly-item-interface</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.leyou</groupId> <artifactId>ly-common</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies>
-
主启动器
@EnableDiscoveryClient @SpringBootApplication public class LyItemService { public static void main(String[] args) { SpringApplication.run(LyItemService.class,args); } }
-
yaml配置
server: port: 8081 spring: application: name: item-service datasource: username: root password: root url: jdbc:mysql://localhost:3306/yun6 eureka: client: fetch-registry: true # 是否拉取其他服务列表 service-url: defaultZone: http://127.0.0.1:10086/eureka instance: ip-address: 127.0.0.1 instance-id: ${spring.application.name} lease-expiration-duration-in-seconds: 10 #10s不发送就过期 lease-renewal-interval-in-seconds: 5 # 5s一次心跳
-
service类
@Service public class ItemService { public Item saveItem(Item item){ Integer i = new Random().nextInt(100); item.setId(i); return item; } }
-
controller类
@RestController @RequestMapping(value = "item") public class ItemController { @Autowired private ItemService itemService; @PostMapping public ResponseEntity<Item> saveItem(Item item){ if(Objects.isNull(item.getPrice())){ throw new LyException(LyExceptionEnum.PRICE_NOT_NULL_EXCEPTION); } Item saveItem = itemService.saveItem(item); return ResponseEntity.status(HttpStatus.CREATED).body(saveItem); } }
ly-common
-
由于需要使用controller级别的注解,引入SpringMVC依赖;
<dependencies> <!--log依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <!--jaskon依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.6</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>8.5.23</version> </dependency> <!--spring core依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.0.9.RELEASE</version> </dependency> <!--lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--webmvc依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> </dependencies>
-
Cookie工具类
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; public final class CookieUtils { protected static final Logger logger = LoggerFactory.getLogger(CookieUtils.class); /** * 得到Cookie的值, 不编码 * * @param request * @param cookieName * @return */ public static String getCookieValue(HttpServletRequest request, String cookieName) { return getCookieValue(request, cookieName, false); } /** * 得到Cookie的值, * * @param request * @param cookieName * @return */ public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) { Cookie[] cookieList = request.getCookies(); if (cookieList == null || cookieName == null){ return null; } String retValue = null; try { for (int i = 0; i < cookieList.length; i++) { if (cookieList[i].getName().equals(cookieName)) { if (isDecoder) { retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8"); } else { retValue = cookieList[i].getValue(); } break; } } } catch (UnsupportedEncodingException e) { logger.error("Cookie Decode Error.", e); } return retValue; } /** * 得到Cookie的值, * * @param request * @param cookieName * @return */ public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) { Cookie[] cookieList = request.getCookies(); if (cookieList == null || cookieName == null){ return null; } String retValue = null; try { for (int i = 0; i < cookieList.length; i++) { if (cookieList[i].getName().equals(cookieName)) { retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString); break; } } } catch (UnsupportedEncodingException e) { logger.error("Cookie Decode Error.", e); } return retValue; } /** * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) { setCookie(request, response, cookieName, cookieValue, -1); } /** * 设置Cookie的值 在指定时间内生效,但不编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) { setCookie(request, response, cookieName, cookieValue, cookieMaxage, false); } /** * 设置Cookie的值 不设置生效时间,但编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, boolean isEncode) { setCookie(request, response, cookieName, cookieValue, -1, isEncode); } /** * 设置Cookie的值 在指定时间内生效, 编码参数 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) { doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode); } /** * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码) */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) { doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString); } /** * 删除Cookie带cookie域名 */ public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) { doSetCookie(request, response, cookieName, "", -1, false); } /** * 设置Cookie的值,并使其在指定时间内生效 * * @param cookieMaxage * cookie生效的最大秒数 */ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) { try { if (cookieValue == null) { cookieValue = ""; } else if (isEncode) { cookieValue = URLEncoder.encode(cookieValue, "utf-8"); } Cookie cookie = new Cookie(cookieName, cookieValue); if (cookieMaxage > 0) cookie.setMaxAge(cookieMaxage); if (null != request)// 设置域名的cookie cookie.setDomain(getDomainName(request)); cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { logger.error("Cookie Encode Error.", e); } } /** * 设置Cookie的值,并使其在指定时间内生效 * * @param cookieMaxage * cookie生效的最大秒数 */ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) { try { if (cookieValue == null) { cookieValue = ""; } else { cookieValue = URLEncoder.encode(cookieValue, encodeString); } Cookie cookie = new Cookie(cookieName, cookieValue); if (cookieMaxage > 0) cookie.setMaxAge(cookieMaxage); if (null != request)// 设置域名的cookie cookie.setDomain(getDomainName(request)); cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { logger.error("Cookie Encode Error.", e); } } /** * 得到cookie的域名 */ private static final String getDomainName(HttpServletRequest request) { String domainName = null; String serverName = request.getRequestURL().toString(); if (serverName == null || serverName.equals("")) { domainName = ""; } else { serverName = serverName.toLowerCase(); serverName = serverName.substring(7); final int end = serverName.indexOf("/"); serverName = serverName.substring(0, end); final String[] domains = serverName.split("\\."); int len = domains.length; if (len > 3) { // www.xxx.com.cn domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1]; } else if (len <= 3 && len > 1) { // xxx.com or xxx.cn domainName = domains[len - 2] + "." + domains[len - 1]; } else { domainName = serverName; } } if (domainName != null && domainName.indexOf(":") > 0) { String[] ary = domainName.split("\\:"); domainName = ary[0]; } return domainName; }
-
IdWork工具类
import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.NetworkInterface; /** * <p>名称:IdWorker.java</p> * <p>描述:分布式自增长ID</p> * <pre> * Twitter的 Snowflake JAVA实现方案 * </pre> * 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用: * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000 * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间, * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识), * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。 * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分), * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。 * <p> * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) * * @author Polim */ public class IdWorker { // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) private final static long twepoch = 1288834974657L; // 机器标识位数 private final static long workerIdBits = 5L; // 数据中心标识位数 private final static long datacenterIdBits = 5L; // 机器ID最大值 private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); // 数据中心ID最大值 private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 毫秒内自增位 private final static long sequenceBits = 12L; // 机器ID偏左移12位 private final static long workerIdShift = sequenceBits; // 数据中心ID左移17位 private final static long datacenterIdShift = sequenceBits + workerIdBits; // 时间毫秒左移22位 private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final static long sequenceMask = -1L ^ (-1L << sequenceBits); /* 上次生产id时间戳 */ private static long lastTimestamp = -1L; // 0,并发控制 private long sequence = 0L; private final long workerId; // 数据标识id部分 private final long datacenterId; public IdWorker(){ this.datacenterId = getDatacenterId(maxDatacenterId); this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); } /** * @param workerId * 工作机器ID * @param datacenterId * 序列号 */ public IdWorker(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } this.workerId = workerId; this.datacenterId = datacenterId; } /** * 获取下一个ID * * @return */ public synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { // 当前毫秒内,则+1 sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { // 当前毫秒内计数满了,则等待下一秒 timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; // ID偏移组合生成最终的ID,并返回ID long nextId = ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; return nextId; } private long tilNextMillis(final long lastTimestamp) { long timestamp = this.timeGen(); while (timestamp <= lastTimestamp) { timestamp = this.timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } /** * <p> * 获取 maxWorkerId * </p> */ protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { StringBuffer mpid = new StringBuffer(); mpid.append(datacenterId); String name = ManagementFactory.getRuntimeMXBean().getName(); if (!name.isEmpty()) { /* * GET jvmPid */ mpid.append(name.split("@")[0]); } /* * MAC + PID 的 hashcode 获取16个低位 */ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); } /** * <p> * 数据标识id部分 * </p> */ protected static long getDatacenterId(long maxDatacenterId) { long id = 0L; try { InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); if (network == null) { id = 1L; } else { byte[] mac = network.getHardwareAddress(); id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; id = id % (maxDatacenterId + 1); } } catch (Exception e) { System.out.println(" getDatacenterId: " + e.getMessage()); } return id; } }
-
JsonUtils工具类
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.Nullable; import java.io.IOException; import java.util.List; import java.util.Map; /** * @author: HuYi.Zhang * @create: 2018-04-24 17:20 **/ public class JsonUtils { public static final ObjectMapper mapper = new ObjectMapper(); private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class); @Nullable public static String toString(Object obj) { if (obj == null) { return null; } if (obj.getClass() == String.class) { return (String) obj; } try { return mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { logger.error("json序列化出错:" + obj, e); return null; } } @Nullable public static <T> T toBean(String json, Class<T> tClass) { try { return mapper.readValue(json, tClass); } catch (IOException e) { logger.error("json解析出错:" + json, e); return null; } } @Nullable public static <E> List<E> toList(String json, Class<E> eClass) { try { return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass)); } catch (IOException e) { logger.error("json解析出错:" + json, e); return null; } } @Nullable public static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) { try { return mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass)); } catch (IOException e) { logger.error("json解析出错:" + json, e); return null; } } @Nullable public static <T> T nativeRead(String json, TypeReference<T> type) { try { return mapper.readValue(json, type); } catch (IOException e) { logger.error("json解析出错:" + json, e); return null; } } @Data @NoArgsConstructor @AllArgsConstructor static class User{ private String name; private Integer age; } public static void main(String[] args) { User user = new User("谢兰",22); /*//toString String json = toString(user); System.out.println("json = " + json); //反序列化 User user1 = toBean(json, User.class); System.out.println("user1 = " + user1); //toList json = "[25,40,15,10]"; List<Integer> list = toList(json, Integer.class); System.out.println("list = " + list);*/ //toMap /*String json = "{\"name\":\"谢兰\",\"age\":\"22\"}"; Map<String, String> stringStringMap = toMap(json, String.class, String.class); System.out.println("stringStringMap = " + stringStringMap);*/ //复杂对象拆分使用TypeReference String json = "[{\"name\":\"谢兰\",\"age\":\"22\"},{\"name\":\"余海\",\"age\":\"21\"}]"; List<Map<String, String>> mapList = nativeRead(json, new TypeReference<List<Map<String, String>>>() { }); mapList.forEach(map -> { System.out.println("map = " + map); }); } }
-
NumberUtils工具类
import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author: HuYi.Zhang * @create: 2018-04-25 09:13 **/ public class NumberUtils { public static boolean isInt(Double num) { return num.intValue() == num; } /** * 判断字符串是否是数值格式 * @param str * @return */ public static boolean isDigit(String str){ if(str == null || str.trim().equals("")){ return false; } return str.matches("^\\d+$"); } /** * 将一个小数精确到指定位数 * @param num * @param scale * @return */ public static double scale(double num, int scale) { BigDecimal bd = new BigDecimal(num); return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue(); } // 从字符串中根据正则表达式寻找,返回找到的数字数组 public static Double[] searchNumber(String value, String regex){ List<Double> doubles = new ArrayList<>(); Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(value); if(matcher.find()) { MatchResult result = matcher.toMatchResult(); for (int i = 1; i <= result.groupCount(); i++) { doubles.add(Double.valueOf(result.group(i))); } } return doubles.toArray(new Double[doubles.size()]); } /** * 生成指定位数的随机数字 * @param len * @return */ public static String generateCode(int len){ len = Math.min(len, 8); int min = Double.valueOf(Math.pow(10, len - 1)).intValue(); int num = new Random().nextInt(Double.valueOf(Math.pow(10, len + 1)).intValue() - 1) + min; return String.valueOf(num).substring(0,len); } }
-
全局controller拦截器
import com.leyou.common.enums.LyExceptionEnum; import com.leyou.common.exceoption.LyException; import com.leyou.common.vo.ExceptionResult; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; /** * Author:Steven.yu * Description:com.leyou.common.utils#CommonExceptionHandler */ @ControllerAdvice public class CommonExceptionHandler { @ExceptionHandler(LyException.class)//拦截的对象和局部对象应与controller抛出异常的对象类型保持一致 public ResponseEntity<ExceptionResult> handler(LyException e){ LyExceptionEnum lyExceptionEnum = e.getLyExceptionEnum(); return ResponseEntity.status(lyExceptionEnum.getCode()).body(new ExceptionResult(lyExceptionEnum)); } }
-
枚举类
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; /** * Author:Steven.yu * Description:com.leyou.common.enums#LyExceptionEnum */ @Getter @NoArgsConstructor @AllArgsConstructor public enum LyExceptionEnum { PRICE_NOT_NULL_EXCEPTION(400,"价格不能为空!"); //写入变量之前应有一个分号,自动匹配构造函数,有多个静态成员时用逗号分隔 private Integer code; private String msg; }
-
定义一个异常对象,继承自RuntimeException
import com.leyou.common.enums.LyExceptionEnum; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; /** * Author:Steven.yu * Description:com.leyou.common.exceoption#LyException */ @Getter @NoArgsConstructor @AllArgsConstructor public class LyException extends RuntimeException{ private LyExceptionEnum lyExceptionEnum; }
-
最终返回对象
/** * Author:Steven.yu * Description:com.leyou.common.vo#ExceptionResult */ @Data public class ExceptionResult { private Integer code; private String msg; private Long timestamp; public ExceptionResult(LyExceptionEnum em){ this.code = em.getCode(); this.msg = em.getMsg(); this.timestamp = System.currentTimeMillis(); } }