用Spring Cloud Alibaba构建用户中心!只要5分钟

2022-06-13 09:16:42 浏览数 (1)

Java 面试辅导来啦!田哥和你面对面,一对一 规划如何准备面试、如何与面试官对话。涵盖内容有:修改简历一对一模拟面试、常见八股文、25w字面试小抄项目实战源码分析等优质内容。 更新汇总: https://www.yuque.com/cwnait/sxhgy9/kyqm2r

你好,我是田哥。前几天,有几位朋友私信我,叫我写一个使用Spring Cloud Alibaba 搭建项目。

今天,我给安排上,使用Spring Cloud Alibaba 搭建一个用户中心。

下面,我就来给大家说一下,我饿还是如何搭建的,具体步骤如下:

  • 使用IDEA创建项目结构
  • 添加maven相关依赖
  • 安装Nacos
  • 业务代码

整个技术栈:Spring Boot Dubbo Nacos MyBatis MySQL

创建项目结构

我们先来创建父项目user-center,打开IDEA,进入File菜单。

然后,选择next

如果你的ArtifactId太长了,其中很多单词使用-分割,那在这里最好把你的复制一遍,后面有用。

选择好自己的maven和本地仓库配置文件setting.xml

点击finish,那么一个简单的项目就创建了。

下面我们来创建modules

和前面一样

这里我们需要填写自己的module名称,比如:user-web或者user-service或者 user-api

然后就是next、next、最后就是finish(注意项目名称使用-的情况,和尚庙创建父项目一样)。

同理,我们可以通过上面的方法创建对应的module。

注意:我们的父项目user-center不做任何业务相关,所以,我们需要把父项目user-center中的src目录给删除。

然后,整个项目就变成了:

添加maven依赖

我们使用父项目进行版本管理,即user-center中的pom.xml内容如下:

代码语言:javascript复制
<?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>
    <packaging>pom</packaging>
    <modules>
        <module>user-web</module>
        <module>user-service</module>
        <module>user-api</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
    </parent>

    <groupId>com.tian</groupId>
    <artifactId>user-center</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>user-center</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

user-api主要给服务消费者和服务提供者共同使用那部分代码,也就是提供给外部的api和相关共用代码。

user-api中pom.xml内容:

代码语言:javascript复制
<?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>

    <parent>
        <groupId>com.tian</groupId>
        <artifactId>user-center</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>user-api</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>user-api</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
</project>

user-service是业务具体实现

user-service中pom.xml内容:

代码语言:javascript复制
<?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>

    <parent>
        <groupId>com.tian</groupId>
        <artifactId>user-center</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>user-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>user-service</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.59</version>
        </dependency>
        <!-- 把user-api引进来-->
        <dependency>
            <groupId>com.tian</groupId>
            <artifactId>user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>
    </dependencies>
</project>

user-web是用户管理的页面系统

user-web中的pom.xml内容:

代码语言:javascript复制
<?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>

    <parent>
        <groupId>com.tian</groupId>
        <artifactId>user-center</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>user-web</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>user-web</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>
        <dependency>
            <groupId>com.tian</groupId>
            <artifactId>user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

以上就是整个项目的整体结构。

代码语言:javascript复制
user-center
|--user-api
|--user-service
|--user-web

项目整体结构以及搭建完成,我们现在把Nacos server端给搞定。

Nacos 安装

Nacos官网地址:https://nacos.io/

Nacos源码地址:https://github.com/alibaba/nacos

进入https://github.com/alibaba/nacos/releases

直接选择对应下载包接口:

下载下来,然后解压,建议配置成咱们自己的数据库,比如MySQL数据库。在conf目录下

application.properties配置文件中。

另外,一定要记得,创建数据库,在此数据库下执行脚本:nacos-mysql.sql

最后数据库中的表,有如下:

Linux/Unix/Mac 操作系统中使用下面命令启动Nacos(单机模式),找到Nacos的bin目录下:

代码语言:javascript复制
sh startup.sh -m standalone

注意:必须安装有JVM,因为nacos是Java 开发的产品。

Windows 操作系统中,打开CMD,来到Nacos的bin目录下:

代码语言:javascript复制
startup.cmd -m standalone

快速开始,请参官方文档,中文版请求地址:

https://nacos.io/zh-cn/docs/quick-start.html

项目启动后,我们直接访问:

http://localhost:8848/nacos/

如果需要输入用户名和密码,则世界输入nacos/nacos

这里有数据,是因为我的服务已经注册上去了。

这里的配置管理 表示 nacos作为配置中心的相关管理。服务管理 便是我们的服务注册信息管理,其他这里不做讨论。

本文中,nacos所处位置:

业务代码

本文的重点在于构建项目基础架构,所以,本文中不会展示过多的业务代码。

user-api

这个module主要是服务提供者和服务消费者共同使用的代码,通常包括:service接口、数据传输对象DTO、一些工具类。

我们定义一类service接口类:

代码语言:javascript复制
public interface UserService {
    UserInfoDTO findUserInfoById(Long id);

    UserInfoDTO findUserInfo(String userName, String password);
}

一个数据传输对象(注意需要实现Serializable用作序列化):

代码语言:javascript复制
public class UserInfoDTO implements Serializable {
    private Long id;
    private String userName;
    private Integer age;
    private Integer gender;
    private String phone;
    
    // 省略 get set
}

user-service

也叫user-provider,就这个意思,懂了就行,另外,在项目开发中,遵循项目开发命名规范来就行。这个module里才是我们真正的业务处理,还有就是数据库操作也基本上在这里面。

下面我把代码都贴一遍。

application.properties配置文件:

代码语言:javascript复制
server.port=9002
spring.application.name=user-service

# dubbo 服务扫描基础包路径
dubbo.scan.base-packages=com.tian
dubbo.protocol.id=dubbo
# Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称,port 为协议端口( -1 表示自增端口,从 20880 开始)
dubbo.protocol.name=dubbo
dubbo.protocol.port=28801

spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/user-center?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

mybatis.mapper-locations=classpath:mapper/**/*.xml
mybatis.type-aliases-package=com.tian.entity
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

UserServiceApplication项目启动类:

代码语言:javascript复制
@SpringBootApplication
@MapperScan("com.tian.mapper")
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

数据库表对应的实体类:

代码语言:javascript复制
public class User {
    private Long id;
    private String userName;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    
    //省略 set get
    
}

mapper接口类和xml:

代码语言:javascript复制
<?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="com.tian.mapper.UserMapper">
    <resultMap id="BaseResultMap" type="com.tian.entity.User">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="user_name" property="userName" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
        <result column="age" property="age" jdbcType="INTEGER"/>
        <result column="gender" property="gender" jdbcType="INTEGER"/>
        <result column="phone" property="phone" jdbcType="VARCHAR"/>
    </resultMap>

    <sql id="BaseSQL">
        id,user_name,age,gender,phone
    </sql>

    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="long">
        select
        <include refid="BaseSQL"/>
        from t_user where id=#{id}
    </select>

    <select id="findUserInfo" resultMap="BaseResultMap">
        select
        <include refid="BaseSQL"/>
        from t_user where user_name =#{userName} and password=#{password}
    </select>
</mapper>
代码语言:javascript复制
public interface UserMapper {

    User selectByPrimaryKey(Long uId);

    User findUserInfo(@Param("userName") String userName, @Param("password") String password);
}

业务具体实现类(注意:这里的Service注解是dubbo中,不是spring中的):

代码语言:javascript复制
@Service(protocol = "dubbo")
public class UserServiceImpl implements UserService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private UserMapper userMapper;

    @Override
    public UserInfoDTO findUserInfoById(Long id) {
        logger.info("通过id查询用户信息,id={}", id);
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            logger.info("用户信息不存在,id={}", id);
            return null;
        }
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        try {
            BeanUtils.copyProperties(userInfoDTO, user);
        } catch (Exception ex) {
            logger.error("bean 转换失败", ex);
        }
        return userInfoDTO;
    }

    @Override
    public UserInfoDTO findUserInfo(String userName, String password) {
        User user = userMapper.findUserInfo(userName, password);
        if(user == null){
            return null;
        }
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        try {
            BeanUtils.copyProperties(userInfoDTO, user);
        } catch (Exception ex) {
            logger.error("bean 转换失败", ex);
        }
        return userInfoDTO;
    }
}

user-web

为了演示nacos作为分布式配置,所以,这个项目中的配置文件有所不同。

bootstrap.properties配置文件:

代码语言:javascript复制
spring.application.name=user-web

spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.file-extension=properties

UserController类:

代码语言:javascript复制
@RestController
@RequestMapping("/user")
@RefreshScope//只需要在需要动态读取配置的类上添加此注解就可以使用@Value注解获取配置项
public class UserController {

    @Resource
    private IUserInfoService userInfoService;

    /**
     * nacos 作为配置中心 验证
     */
    @Value("${config.test}")
    private String configName;

    @GetMapping("/info/{id}")
    public ResultData findUserInfoById(@PathVariable("id") Long id) {
        //输出我们在nacos配置中心配置的内容
        System.out.println(configName);
        return userInfoService.findUserInfoById(id);
    }

    @PostMapping(value = "/login")
    public ResultData login(@RequestParam("userName") String userName,
                            @RequestParam("password") String password) {
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            return ResultData.fail(ResultCodeEnum.PARAM_EMPTY.getCode(), ResultCodeEnum.PARAM_EMPTY.getMsg());
        }
        return userInfoService.login(userName, password);
    }
}

在user-web中,我们通常也会定义一个service目录,可以做一些数据包装转换之类的。

代码语言:javascript复制
public interface IUserInfoService {

    /**
     *  查询用户信息
     */
    ResultData findUserInfoById(Long id);

    /**
     *  用户登录
     */
    ResultData login(String userName, String password);
}

实现类(注意:@Reference这个注解是Dubbo中的,protocol指定协议):

代码语言:javascript复制
@Service
public class UserInfoServiceImpl implements IUserInfoService {

    @Reference(protocol = "dubbo")
    private UserService userService;

    @Override
    public ResultData findUserInfoById(Long id) {
        UserInfoDTO userInfoDTO = userService.findUserInfoById(id);
        if (userInfoDTO == null) {
            return ResultData.fail(ResultCodeEnum.SYSTEM_ERROR.getCode(), ResultCodeEnum.SYSTEM_ERROR.getMsg());
        }
        return ResultData.success(userInfoDTO);
    }

    @Override
    public ResultData login(String userName, String password) {
        UserInfoDTO userInfoDTO =userService.findUserInfo(userName, password);
        if (userInfoDTO == null) {
            return ResultData.fail(ResultCodeEnum.LOGIN_FAILD.getCode(), ResultCodeEnum.LOGIN_FAILD.getMsg());
        }
        return ResultData.success(userInfoDTO);
    }
}

项目启动类:

代码语言:javascript复制
@SpringBootApplication
public class WebApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }
}

ResultData返回数据类:

代码语言:javascript复制
public class ResultData<T> {

    private T data;
    private int code;
    private String msg;

    public static <T> ResultData<T> success(T data) {
        return new ResultData(data, ResultCodeEnum.LOGIN_SUCCESS.getCode(), ResultCodeEnum.LOGIN_SUCCESS.getMsg());
    }

    public static <T> ResultData<T> fail(int code, String errorMsg) {
        return new ResultData(null, code, errorMsg);
    }
}

ResultCodeEnum返回码类:

代码语言:javascript复制
public enum ResultCodeEnum {
    SUCCESS(200, "操作成功"),
    SYSTEM_ERROR(500, "系统错误"),
    PARAM_EMPTY(400, "参数为空"),
    LOGIN_SUCCESS(200, "登录成功"),
    LOGIN_FAILD(500, "登录失败");

    private int code;
    private String msg;
    //省略 相关非核心代码
}

好了,以上就是构建一个用户中心的主要代码,大家也可以在此基础之上,进行添加一些功能。同时还可以添加请求和相应参数的打印,也可以做一个统一异常处理。

后记

通过文中的方法,我们同样可以构建商品中心、订单中心,这样不就可以简单的构建一个电商项目了么?

好了,今天就分享到这里~

0 人点赞