Springcloud实战:开发课程查询功能(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Springcloud实战:开发课程查询功能(二)

course-price(课程价格服务)



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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.changlu</groupId>
        <artifactId>course-service</artifactId>
        <version>1.0.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>course-price</artifactId>
    <version>1.0.0</version>
    <name>course-price</name>
    <description>springcloud demo for course-price</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--    远程调用:feign    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--    引入断路器模块    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--   引入包含pojo模块,解决client的报错问题     -->
        <dependency>
            <groupId>com.changlu</groupId>
            <artifactId>course-list</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>



application.yaml:


spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  application:
    name: course-price   # 应用名
server:
  port: 8081
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/
# 开启负载均衡
#ribbon:
#  eureka:
#    enabled: true
# 服务id=>命名空间=>配置属性
course-list:   # 当前远程调用的服务application名
  ribbon:
    NFLoadBanlancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  # 轮询策略
# 开启断路器
feign:
  hystrix:
    enabled: true



client目录中远程调用及断路器实现类:


/**
 * @ClassName CourseListClient
 * @Author ChangLu
 * @Date 2021/10/4 16:36
 * @Description 远程调用
 */
@FeignClient(value = "course-list",fallback = CourseListClientHystrix.class)
@Primary
public interface CourseListClient {
    @GetMapping("/course/list")
    List<Course> getList();
}
/**
 * @ClassName CourseListClientHystrix
 * @Author ChangLu
 * @Date 2021/10/4 20:30
 * @Description 断路器,对于服务不可用或其他情况进行统一的返回值返回
 */
@Component
public class CourseListClientHystrix implements CourseListClient{
    @Override
    public List<Course> getList() {
        Course course = new Course();
        course.setId(0);
        course.setCourseId(0);
        course.setName("Java从入门到精通");
        course.setValid(0);
        return Collections.singletonList(course);
    }
}


启动器:


@SpringBootApplication
@MapperScan("com.changlu.courselist.mapper")
@EnableFeignClients
@EnableCircuitBreaker    //打开断路器
public class CoursePriceApplication {
    public static void main(String[] args) {
        SpringApplication.run(CoursePriceApplication.class, args);
    }
}


pojo、controller、service汇总


//pojo
@Data
public class CoursePrice implements Serializable {
    private static final long serialVersionUID = -6849794470748667710L;
    private Integer id;
    private Integer courseId;
    private BigDecimal price;
}
/**
 * @ClassName CourseAndPrice
 * @Author ChangLu
 * @Date 2021/10/5 7:15
 * @Description TODO
 */
@Data
public class CourseAndPrice extends Course implements Serializable {
    private static final long serialVersionUID = -6855794470748667710L;
    private BigDecimal price;
}
//controller
@RestController
@RequestMapping("/courseprice")
public class CoursePriceController {
    @Autowired
    private CoursePriceService coursePriceService;
    //远程调用动态代理类注入
    @Autowired
    private CourseListClient courseListClient;
    @GetMapping("/list/{id}")
    public CoursePrice getList(@PathVariable("id")Integer id){
        return  coursePriceService.getCoursePriceByCourseId(id);
    }
    @GetMapping("/test")
    public List<Course> testFeignCourseService(){
        return courseListClient.getList();
    }
    @GetMapping("/courseprice")
    public List<CourseAndPrice> getAllCourseAndPrice(){
        return coursePriceService.getAllCourseAndPrice();
    }
}
//service
public interface CoursePriceService {
    /**
     * 根据课程id查询到课程价格
     * @param courseId
     * @return
     */
    CoursePrice getCoursePriceByCourseId(Integer courseId);
    /**
     * 查询出所有的课程及价格
     * @return
     */
    List<CourseAndPrice> getAllCourseAndPrice();
}
@Service
public class CoursePriceServiceImpl implements CoursePriceService {
    @Autowired
    private CoursePriceMapper coursePriceMapper;
    @Autowired
    private CourseListClient courseListClient;
    @Override
    public CoursePrice getCoursePriceByCourseId(Integer courseId) {
        return coursePriceMapper.selectOne(new LambdaQueryWrapper<CoursePrice>()
                .eq(CoursePrice::getCourseId,courseId)
        );
    }
    @Override
    public List<CourseAndPrice> getAllCourseAndPrice() {
        //远程调用课程服务,查询出所有的课程
        List<Course> courses = courseListClient.getList();
        List<CourseAndPrice> newCourses = new ArrayList<>(courses.size());
        if(!CollectionUtils.isEmpty(courses)){
            for (Course course : courses) {
                CourseAndPrice courseAndPrice = new CourseAndPrice();
                BeanUtils.copyProperties(course, courseAndPrice);
                //本地查询
                CoursePrice price = this.getCoursePriceByCourseId(course.getCourseId());
                courseAndPrice.setPrice(price.getPrice());
                newCourses.add(courseAndPrice);
            }
        }
        return newCourses;
    }
}
//mapper
public interface CoursePriceMapper extends BaseMapper<CoursePrice> {
}


该服务注册到服务中心,并且进行了远程调用course-list模块、断路器实现以及负载均衡ribbon。



course-zuul(网关服务)



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>spring-cloud-course-practice</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>course-zuul</artifactId>
    <dependencies>
        <!--    用于服务注册     -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--    zuul网关     -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>


application.yaml:


spring:
  application:
    name: zuul-gateway
server:
  port: 9000
# 指定注册的服务中心地址,一般与eureka-server中配置的对应,此时该服务启动就会将自己注册到服务中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/
# zuul的相关配置
zuul:
  prefix: /changlu   # 访问zuul网关的前缀url(由原来的/ => /changlu)
  routes:            # 路由配对,下面有两组服务
    course-list:
      path: /list/**             # 2、指定的服务路由转换 (例如由原来的/course-list => /list)
      service-id: course-list    # 1、指定的服务名(application name):课程服务
    course-price:
      path: /price/**
      service-id: course-price


启动器:


/**
 * @ClassName ZuulGatewayApplication
 * @Author ChangLu
 * @Date 2021/10/5 8:27
 * @Description 网关启动类
 */
@EnableZuulProxy
@SpringCloudApplication
public class ZuulGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulGatewayApplication.class,args);
    }
}


两个过滤器:用于进行拦截请求前、后


/**
 * @ClassName PreRequestFilter
 * @Author ChangLu
 * @Date 2021/10/5 9:26
 * @Description 前置请求过滤器
 */
@Component
public class PreRequestFilter extends ZuulFilter {
    @Override
    public String filterType() {
        //过滤器类型
        return FilterConstants.PRE_TYPE;
    }
    @Override
    public int filterOrder() {
        //过滤器顺序
        return 0;  //0-1000 从小到大顺序依次执行,这里表示第一个执行
    }
    @Override
    public boolean shouldFilter() {
        return true;  //是否启动过滤器
    }
    //具体过滤器中执行的方法
    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        currentContext.set("startTime",System.currentTimeMillis());
        System.out.println("前缀过滤器pre已经记录时间");
        return null;
    }
}
/**
 * @ClassName PostRequestFilter
 * @Author ChangLu
 * @Date 2021/10/5 9:31
 * @Description 后置请求处理器
 */
@Component
public class PostRequestFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }
    /**
     * filter执行顺序,值越小优先级越高
     * 官方推荐使用x-1方式优先排序
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER-1;  //响应过滤器为1000,这里-1表示该过滤器越优先执行
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        Long startTime = (Long) currentContext.get("startTime");
        Long duration = System.currentTimeMillis() - startTime;
        String uri = currentContext.getRequest().getRequestURI();
        System.out.println("uri:"+uri+",处理时长为:"+duration);
        return null;
    }
}


设置好网关之后,我们可以通过网关来进行访问我们的服务:


# 第一个是课程服务的一个接口;第二个是课程价格的接口,该接口中包含了远程调用课程服务
http://localhost:9000/changlu/list/course/list    
http://localhost:9000/changlu/price/courseprice/courseprice


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
62 5
|
1月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
60 3
|
2月前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
226 6
|
2月前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
125 2
|
2月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
34 1
|
2月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
79 0
|
2月前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
59 0
|
2月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
54 0
|
3月前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
269 6
|
4月前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
195 0
下一篇
DataWorks