springcloud项目搭建

父工程

  • 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();
      	    }
      	}
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Spring Boot 的优势 使用 Spring Boot 开发项目,会给我们带来非常美妙的开发体验,可以从以下几个方面展开来说明 Spring Boot 让开发变得更简单 Spring Boot 对开发效率的提升是全方位的,我们可以简单做一下对比: 在没有使用 Spring Boot 之前我们开发一个 web 项目需要做哪些工作: 1)配置 web.xml,加载 Spring 和 Spring mvc 2)配置数据库连接、配置 Spring 事务 3)配置加载配置文件的读取,开启注解 4)配置日志文件 … n) 配置完成之后部署 tomcat 调试 可能你还需要考虑各个版本的兼容性,jar 包冲突的各种可行性。 那么使用 Spring Boot 之后我们需要开发一个 web 项目需要哪些操作呢? 1)登录网址 http://start.spring.io/ 选择对应的组件直接下载 2)导入项目,直接开发 上面的 N 步和下面的2步形成巨大的反差,这仅仅只是在开发环境搭建的这个方面。 Spring Boot 使测试变得更简单 Spring Boot 对测试的支持不可谓不强大,Spring Boot 内置了7种强大的测试框架: JUnit: 一个 Java 语言的单元测试框架 Spring Test & Spring Boot Test:为 Spring Boot 应用提供集成测试和工具支持 AssertJ:支持流式断言的 Java 测试框架 Hamcrest:一个匹配器库 Mockito:一个 java mock 框架 JSONassert:一个针对 JSON 的断言库 JsonPath:JSON XPath 库 我们只需要在项目中引入 spring-boot-start-test依赖包,就可以对数据库、Mock、 Web 等各种情况进行测试。 Spring Boot Test 中包含了我们需要使用的各种测试场景,满足我们日常项目的测试需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值