毕业设计(二)完成服务注册与使用

in 毕业设计 with 0 comment

上节说到SpringCloud的注册中心Eureka的集群,这篇博客将搭建服务的注册与使用。主要使用的SpringCloud有Ribbon负载均衡和Feigh远程调用。

项目目录结构

还是一样的,使用Maven的聚合父子工程。
这次是一个完整的web项目的Demo,主要测试SpringCloud在服务之间调用是否成功
image.png
同样的,采用MVC三层架构开发。其中mapper是Dao层,pojo是我们的实体类,student-service是我们的服务提供者,student-web是我们的服务消费者。
mapper使用的是Mybatis框架。故而,现在开始创建数据库!

数据库

image.png
因为简单的小测试服务之间是否正常,所以表设计都很简单,就是四个字段。id主键自增、usernumber是学号,password是密码,username是用户真实姓名。暂时先这样设置吧。

具体代码实现

既然是MVC三层架构,就从实体类开始吧,先看下pojo

pojo

在pojo使用了lombok方便实体类的使用和代码的简洁,主要是配合Mybatis方便ORM映射数据库的字段。

@Data
public class User {
    private int id;
    private String userNumber;
    private String password;
    private String username;
}

mapper

再看mapper,是dao层,操作数据库。这里主要是测试,就是实现了一个简单的登陆功能。主要使用的jar包也没什么区别,和boot开发一样。

mapper接口

@Mapper
public interface UserMapper {
    User loginCheck(@Param("user") User user);
}

SQL配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.penglei.mapper.Mapper.UserMapper">
    <select id="loginCheck" parameterType="cn.penglei.pojo.User" resultType="cn.penglei.pojo.User">
        select id,userNumber,password,username
        from user
        where userNumber = #{user.userNumber} and password = #{user.password}
        limit 1
    </select>
</mapper>

很简单的需求,就是通过学号和密码,登陆

Mybatis集成SpringBoot配置文件

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/tb_project?useUnicode=true&characterEncoding=utf8
    username: root
    password: 98629
mybatis:
  mapper-locations: classpath*:mapper/*.xml

和平常的SpringBoot配置文件没什么区别,但是有个地方值得注意以下。在文件命名方面,这里可以命名为application-mapper.yml,等下就知道为什么了。image.png

student-service

现在开始服务提供者,提供登陆服务给web端调用,其实它自身也可以完成登陆功能,但是没必要在这里完成登陆。
先下它的具体结构
image.png
主要使用的jar包

<dependencies>
<!--        引入当前依赖-->
        <dependency>
            <groupId>cn.penglei</groupId>
            <artifactId>mapper</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>cn.penglei</groupId>
            <artifactId>pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

因为是父子工程,所以要主动导入pojo包和mapper包,可以像jar包一样直接调用
先讲service包,他和普通的单体架构一样,接口加实现类来完成。

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public User loginCheck(User user) {
        return userMapper.loginCheck(user);
    }
}

controller包,和单体架构一样

@RestController
@CrossOrigin
public class MovieController {
    @Value("${server.port}")
    private String port;

    @Autowired
    private UserService userService;
    
    @RequestMapping("/loginCheck")
    public String loginCheck(String userNumber,String password){
        System.out.println(userNumber+"---"+password);
        User user = new User();
        user.setUserNumber(userNumber);
        user.setPassword(password);
        System.out.println("123");
        return "hi " + userService.loginCheck(user).getUsername() + " ,i am from port:" + port;
    }
}

这里加上了端口号这个变量,方便等下看负载均衡的效果。

重头戏来了,配置文件

server:
  port: 8001
spring:
  application:
    #项目名,等下通过项目名找服务
    name: UserServer
  profiles:
    #引入mapper的配置文件
    include: mapper
eureka:
  client:
    service-url:
      # eureka注册地址
      defaultZone: http://127.0.0.1:10001/eureka
management:
  endpoints:
    web:
      exposure:
        # 暴露全部端口
        include: "*"

三个点需要注意:

  1. 项目名现在开始要规范了,因为远程调用就是通过项目名找服务的
  2. 之前我们这是的Mybatis的配置文件加了-mapper就在这里作用了,SpringBoot可以直接通过mapper这个名字找到Mybatis的配置文件,因为我们不会启动mybatis这个module,只是将它作为jar包导入了我们的项目中。
  3. eureka的注册地址

同时,我在这里做了三个集群,保证服务的高可用,嘿嘿。这里另外两个配置文件就是端口号和注册地址不同,其他都是一样的。
启动类加上注解@EnableEurekaClient,开飞。对了,还有包扫描。关于mapper层,SpringBoot现在是找不到的~

@SpringBootApplication(scanBasePackages = {"cn.penglei.mapper","cn.penglei.studentservice.Controller","cn.penglei.studentservice.Service"})
@EnableEurekaClient
public class StudentServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(StudentServiceApplication.class, args);
    }
}

image.png
ok,三台机器启动成功
其实这三台集群每一台都是可以直接访问,地址栏输入

http://localhost:8001/loginCheck?userNumber=20160402087&password=123456

image.png

看来我们的服务提供者是没有问题的。继续消费者

student-web

消费者的项目目录就很简单了。
image.png
主要就是一个远程调用的接口,在就是一个controller层。
先看下jar包

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>cn.penglei</groupId>
            <artifactId>pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <type>jar</type>
        </dependency>
    </dependencies>

我的调用是直接用的Feign这个组件,它直接将ribbon给集成了,在调用方面会方便很多。
接着看下远程调用的接口

@FeignClient("USERSERVER")
public interface StudentService {
    @RequestMapping("/loginCheck")
    String hi(@RequestParam(value = "userNumber") String usernumber,@RequestParam(value = "password") String password);
}

这里就是通过我们刚才服务提供者的名字找到我们所需要的服务,在找到它的请求地址,就可以完成我们的功能啦。

继续Controller

@RestController
@CrossOrigin
public class StudentController {
    @Autowired
    StudentService studentService;
    @RequestMapping("loginCheck")
    public String loginCheck(String userNumber,String password){
        System.out.println(userNumber+"---"+password);
        return studentService.hi(userNumber,password);
    }
}

这里的Controller就再普通不过了,直接就是调用service层,我现在的service层就是远程调用的服务。

然后再给启动类加上注解就启动吧!

@SpringBootApplication
//打开eureka
@EnableDiscoveryClient
//打开feign
@EnableFeignClients
public class StudentWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(StudentWebApplication.class, args);
    }
}

启动成功
image.png

项目测试

现在所有module都启动成功了,来快乐的玩耍一把吧
访问地址

http://localhost:9001/loginCheck?userNumber=20160402087&password=123456

image.png
调用成功,继续刷新该页面
image.png
image.png
image.png

好了,没啥问题看来,负载均衡也确实是使用的默认的轮询算法。
那现在我的毕设又进了一步。哈哈