前几天,有几位朋友私信我,叫我写一个使用Spring Cloud Alibaba 搭建项目。
今天,我给安排上,使用Spring Cloud Alibaba 搭建一个用户中心。
下面,我就来给大家说一下,我饿还是如何搭建的,具体步骤如下:
整个技术栈: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目录给删除。
然后,整个项目就变成了:
我们使用父项目进行版本管理,即user-center中的pom.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
pom
user-web
user-service
user-api
org.springframework.boot
spring-boot-starter-parent
2.3.0.RELEASE
com.tian
user-center
1.0-SNAPSHOT
user-center
UTF-8
1.8
1.8
2.3.0.RELEASE
2.2.1.RELEASE
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba.version}
pom
import
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
user-api主要给服务消费者和服务提供者共同使用那部分代码,也就是提供给外部的api和相关共用代码。
user-api中pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
com.tian
user-center
1.0-SNAPSHOT
user-api
1.0-SNAPSHOT
user-api
UTF-8
1.8
1.8
user-service是业务具体实现
user-service中pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
com.tian
user-center
1.0-SNAPSHOT
user-service
1.0-SNAPSHOT
user-service
UTF-8
1.7
1.7
org.springframework.boot
spring-boot-starter
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.cloud
spring-cloud-starter-dubbo
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
mysql
mysql-connector-java
com.alibaba
fastjson
1.2.59
com.tian
user-api
1.0-SNAPSHOT
commons-beanutils
commons-beanutils
1.8.3
user-web是用户管理的页面系统
user-web中的pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
com.tian
user-center
1.0-SNAPSHOT
user-web
1.0-SNAPSHOT
user-web
org.springframework.boot
spring-boot-starter
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
com.alibaba.cloud
spring-cloud-starter-dubbo
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
com.alibaba
fastjson
1.2.56
com.tian
user-api
1.0-SNAPSHOT
以上就是整个项目的整体结构。
user-center
|--user-api
|--user-service
|--user-web
项目整体结构以及搭建完成,我们现在把Nacos server端给搞定。
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目录下:
sh startup.sh -m standalone
注意:必须安装有JVM,因为nacos是Java 开发的产品。
在Windows 操作系统中,打开CMD,来到Nacos的bin目录下:
startup.cmd -m standalone
快速开始,请参官方文档,中文版请求地址:
https://nacos.io/zh-cn/docs/quick-start.html
项目启动后,我们直接访问:
http://localhost:8848/nacos/
如果需要输入用户名和密码,则世界输入nacos/nacos
这里有数据,是因为我的服务已经注册上去了。
这里的配置管理 表示 nacos作为配置中心的相关管理。服务管理 便是我们的服务注册信息管理,其他这里不做讨论。
本文中,nacos所处位置:
本文的重点在于构建项目基础架构,所以,本文中不会展示过多的业务代码。
这个module主要是服务提供者和服务消费者共同使用的代码,通常包括:service接口、数据传输对象DTO、一些工具类。
我们定义一类service接口类:
public interface UserService {
UserInfoDTO findUserInfoById(Long id);
UserInfoDTO findUserInfo(String userName, String password);
}
一个数据传输对象(注意需要实现Serializable用作序列化):
public class UserInfoDTO implements Serializable {
private Long id;
private String userName;
private Integer age;
private Integer gender;
private String phone;
// 省略 get set
}
也叫user-provider,就这个意思,懂了就行,另外,在项目开发中,遵循项目开发命名规范来就行。这个module里才是我们真正的业务处理,还有就是数据库操作也基本上在这里面。
下面我把代码都贴一遍。
application.properties配置文件:
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项目启动类:
@SpringBootApplication
@MapperScan("com.tian.mapper")
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
数据库表对应的实体类:
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:
<?xml version="1.0" encoding="UTF-8" ?>
id,user_name,age,gender,phone
public interface UserMapper {
User selectByPrimaryKey(Long uId);
User findUserInfo(@Param("userName") String userName, @Param("password") String password);
}
业务具体实现类(注意:这里的Service注解是dubbo中,不是spring中的):
@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;
}
}
为了演示nacos作为分布式配置,所以,这个项目中的配置文件有所不同。
bootstrap.properties配置文件:
spring.application.name=user-web
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.file-extension=properties
UserController类:
@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目录,可以做一些数据包装转换之类的。
public interface IUserInfoService {
/**
* 查询用户信息
*/
ResultData findUserInfoById(Long id);
/**
* 用户登录
*/
ResultData login(String userName, String password);
}
实现类(注意:@Reference这个注解是Dubbo中的,protocol指定协议):
@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);
}
}
项目启动类:
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
ResultData返回数据类:
public class ResultData {
private T data;
private int code;
private String msg;
public static ResultData success(T data) {
return new ResultData(data, ResultCodeEnum.LOGIN_SUCCESS.getCode(), ResultCodeEnum.LOGIN_SUCCESS.getMsg());
}
public static ResultData fail(int code, String errorMsg) {
return new ResultData(null, code, errorMsg);
}
}
ResultCodeEnum返回码类:
public enum ResultCodeEnum {
SUCCESS(200, "操作成功"),
SYSTEM_ERROR(500, "系统错误"),
PARAM_EMPTY(400, "参数为空"),
LOGIN_SUCCESS(200, "登录成功"),
LOGIN_FAILD(500, "登录失败");
private int code;
private String msg;
//省略 相关非核心代码
}
好了,以上就是构建一个用户中心的主要代码,大家也可以在此基础之上,进行添加一些功能。同时还可以添加请求和相应参数的打印,也可以做一个统一异常处理。
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,
咱们下期见!答案获取方式:已赞 已评 已关~
学习更多知识与技巧,关注与私信博主(03)
留言与评论(共有 0 条评论) “” |