乐优商城是一个基于SpringCloud的微服务应用,在正常开发中,每一个服务都应该作为一个完全独立的项目去进行开发,但是在这里所有的服务都由自己进行开发,所以我们创建一个聚合工程来对开发过程进行简化。
创建父工程并修改pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.parent</groupId>
<artifactId>leyou</artifactId>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>ly-registry</module>
<module>ly-gateway</module>
<module>ly-item</module>
<module>ly-common</module>
<module>ly-upload</module>
</modules>
<packaging>pom</packaging>
<name>leyou</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.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.SR1</spring-cloud.version>
<mapper.starter.version>2.0.3</mapper.starter.version>
<mysql.version>5.1.32</mysql.version>
<pageHelper.starter.version>1.2.5</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>
<!-- 通用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>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后我们创建注册中心和网关,注册中心的pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.common</groupId>
<artifactId>ly-registry</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
编写启动类并添加相应注解:
package com.leyou;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class LyRegistryApplication {
public static void main(String[] args) {
SpringApplication.run(LyRegistryApplication.class);
}
}
写配置文件(这里我们不需要注册中心注册自己和拉去服务):
server:
port: 10086
spring:
application:
name: ly-registry
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
fetch-registry: false #是否拉取服务列表
register-with-eureka: false
网关的pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.common</groupId>
<artifactId>ly-gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
编写网关的启动类并添加相应注解:
package com.leyou.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class);
}
}
写配置文件:
server:
port: 10010
spring:
application:
name: ly-gateway
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
ribbon:
ConnectionTimeOut: 1000 #ribbon连接超时时长
ReadTimeOut: 3500 #ribbon读取超时时长
MaxAutoRetries: 0 #当前服务器重试次数
MaxAutoRetriesNextServer: 0 #切换服务器重试次数
这样我们的网关和注册中心就暂时创建完成了
接下来我们创建商品微服务。商品微服务主要作用是被别人调用以进行增删查改,当别人调用我们的商品微服务进行查询时,得到的返回值应当为一个pojo类。但是在实际开发过程中,我们的商品微服务是由一个团队进行独立开发,所以我们应该考虑如何使其他团队在方便的调用商品类的同时又无法查看商品微服务中的其他代码。在这里,我们在总的父工程中创建一个商品微服务子工程,但是这个子工程同样是一个聚合工程由子工程service和interface组成,service中包含了所有的业务逻辑和内部使用接口,interface中主要是相关的实体类,这样当别的团队需要使用商品类时,可以通过引用interface的坐标来获得实体类。
创建商品微服务聚合工程后,先在其中创建interface工程,引入相关依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ly-item</artifactId>
<groupId>com.leyou.service</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.service</groupId>
<artifactId>ly-item-interface</artifactId>
<dependencies>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-core</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
</project>
无需添加启动类也不需要修改配置文件。创建service工程并引入相关依赖,注意,不要忘记将interface的坐标引入否则将无法使用商品类。service工程pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ly-item</artifactId>
<groupId>com.leyou.service</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.service</groupId>
<artifactId>ly-item-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.service</groupId>
<artifactId>ly-item-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>ly-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
添加启动类(记得添加mapper包扫描注解),并填写配置文件如下:
package com.leyou;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@EnableEurekaClient
@MapperScan("com.leyou.item.mapper")
public class LyItemApplication {
public static void main(String[] args) {
SpringApplication.run(LyItemApplication.class);
}
}
server:
port: 8081
spring:
application:
name: item-service
datasource:
url: jdbc:mysql://localhost:3306/yun6
username: root
password: 123
driver-class-name: com.mysql.jdbc.Driver
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
创建好商品微服务工程后记得去修改网关的配置文件。
zuul:
prefix: /api
routes:
item-service: /item/**
我们的商品微服务工程也搭建好了。接下来我们需要创建一个工程,里面存放着供其他工程使用的工具类,此部分和我们的学习内容关联较少,所以不做记录。但是,我们要在此配置全局异常处理。
首先我们自定义一个枚举类如下图所示:
package com.leyou.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnum {
CATEGORY_NOT_FOUND(404,"商品分类没查到"),
BRAND_NOT_FOUND(404,"品牌不存在"),
BRAND_SAVE_ERROR(500,"服务器新增品牌失败"),
UPLOAD_FILE_ERROR(500,"文件上传失败"),
INVALID_FILE_TYPE(400,"无效的文件类型"),
SPEC_GROUP_NOT_FOUND(404,"商品规格组不存在"),
SPEC_PARAM_NOT_FOUND(404,"商品规格参数不存在"),
;
private int code;
private String msg;
}
然后是自定义异常类,此类中包含一个自定义枚举对象。
package com.leyou.common.exception;
import com.leyou.common.enums.ExceptionEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class LyException extends RuntimeException {
private ExceptionEnum exceptionEnum;
}
接着我们来写自定义异常结果,此类中成员变量包含状态码,异常信息,和时间戳。构造方法的参数为自定义枚举类,如下:
package com.leyou.common.vo;
import com.leyou.common.enums.ExceptionEnum;
import lombok.Data;
@Data
public class ExceptionResult {
private int status;
private String message;
private Long timestamp;
public ExceptionResult(ExceptionEnum em) {
this.status = em.getCode();
this.message = em.getMsg();
this.timestamp = System.currentTimeMillis();
}
}
接下来我们写通用异常处理器,底层其实是在抛异常时进行了aop拦截。
package com.leyou.common.advice;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.ExceptionResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(LyException.class)
public ResponseEntity<ExceptionResult> handleException(LyException e) {
ExceptionEnum em = e.getExceptionEnum();
//return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
return ResponseEntity.status(em.getCode()).body(new ExceptionResult(e.getExceptionEnum()));
}
}
需在类上添加注解,并在拦截方法上添加相应注解,括号中填写需处理的异常的字节码。这样全局异常处理就完成了。在以后的开发中,如果出现新的提示信息,我们可以在枚举类型中增加。
第一部分到此为止。