系统管理中心&用户中心
一 课程简介
-
系统管理中心与用户中心需求分析
-
系统管理中心与用户中心需求设计
-
mybatisplus入门
-
系统管理中心
租户类型列表 租户列表 店铺入驻(自己做-百度地图,套餐,异常统一处理)
-
用户中心
用户注册
二 系统管理中心与用户中心需求分析
1 系统管理中心需求分析
1 系统配置 对整个系统做一些全局配置。 fastdfs地址,邮箱,短信 项目一启动就从数据库查询缓存到reids中,以后直接从redis查询 略过 缓存预热
2 部门 略过
3 员工管理 略过
4 租户类型: redis缓存 略过
5 租户:姚桑礼品店,租户入驻,租户购买套餐,简单做一下
6 套餐:关联权限
2 用户中心需求分析
用户角度:
用户基本功能: 用户注册
用户详情信息: 修改基本信息,修改密码,找回密码
实名认证: 条件实名认证
用户地址: crud
用户的成长历史:crud
管理员工:
用户信息
用户实名认证管理
列表+审核
用户地址列表
用户的成长历史
除了注册其他全是crud
三 系统管理中心与用户中心需求设计
页面设计 表设计 流程设计
1 页面设计
1.1 后台管理站点搭建
copy上个admin站点
install
改站点名,标题
修改菜单
店铺入驻…
1.2 用户中心站点搭建
创建gift-websites-user
拷贝静态资源
编写启动bat脚本
运行
====
注册界面
2 系统管理中心与用户中心表设计
3 流程设计
3.1 系统管理中心需求设计
店铺需要先进行注册,然后平台进行审核,审核通过后向商家发送一封激活邮件,商家需要通过激活链接去激活,激活之后商家可正常登陆。
3.2 用户中心需求设计
注册:
发送短信验证码
主流程
以上功能都需要操作数据库,操作数据库使用mybatis,有点弱,玩Mybatis-plus,所以接下来对Mybatis-plus进行入门学习,然后在集成到项目中。
四 mybatisplus入门
1 引入
在真实项目开发中我们的服务模块,一般都要进行数据库操作,并且每个domain都有crud,需多次写重复代码。我们使用MybatisPlus,就不用写重复代码(封装好了基础的crud),并且还有模板的功能,可以一键生成domain,query,mapper接口,mapper.xml,service,controller,非常好用。
反向工程:设计好表,快速生成相关模块
代码生成器:通过表一键生成代码
快开
低代码
2 简介
2.1 是什么
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
支持关键词自动转义:支持数据库关键词(order、key…)自动转义,还可自定义关键词
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击
2.2 结构
3 入门
3.1 结构分析
3.2 运行项目-代码生成器生成要放到里面
导入jar
dependencies-basic:基础依赖jar管理
<dependencies>
<!-- springBoot支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springBoot支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--一些工具依赖-->
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-basic-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
dependencies-core:需要数据库依赖的jar管理
<dependencies>
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-basic</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--mybatisplusjar-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
自己的依赖
<dependencies>
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
做配置
yml
server:
port: 8888
spring:
application:
name: mybaitsplus-test
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
mybatis-plus:
type-aliases-package: cn.ronghuanet.gift.domain,cn.ronghuanet.gift.query
分页插件配置
package cn.ronghuanet.gift.config;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//Spring boot方式
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
入门类
package cn.ronghuanet.gift;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("cn.ronghuanet.gift.mapper")
public class AppStart {
public static void main(String[] args) {
SpringApplication.run(AppStart.class,args);
}
}
测试:启动不报错就是成功
3.3 代码生成器-用来生成代码
导入jar
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
配置
resource/mybatiesplus-config-服务名(英文).properties
#此处为本项目src所在路径(代码生成器输出路径),注意一定是当前项目所在的目录哟
OutputDir=F:\\workspace\\idea_workspace\\mybatisplustest\\src\\main\\java
#mapper.xml SQL映射文件目录
OutputDirXml=F:\\workspace\\idea_workspace\\mybatisplustest\\src\\main\\resources
OutputDirBase=F:\\workspace\\idea_workspace\\mybatisplustest\\src\\main\\java
#设置作者
author=yaohuaipeng
#自定义包路径
parent=cn.ronghuanet.mybatisplus.mybatisplustest
#数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///gift_user
jdbc.user=root
jdbc.pwd=admin
拷贝模板
代码编写
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.*;
/**
* Created by CDHong on 2018/4/6.
*/
public class GenteratorCode {
public static void main(String[] args) throws InterruptedException {
//用来获取Mybatis-Plus.properties文件的配置信息
ResourceBundle rb = ResourceBundle.getBundle("mybatitsPlus-config"); //不要加后缀
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(rb.getString("OutputDir"));
gc.setFileOverride(true);
gc.setActiveRecord(true);// 开启 activeRecord 模式
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
gc.setAuthor(rb.getString("author"));
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert());
dsc.setDriverName(rb.getString("jdbc.driver"));
dsc.setUsername(rb.getString("jdbc.user"));
dsc.setPassword(rb.getString("jdbc.pwd"));
dsc.setUrl(rb.getString("jdbc.url"));
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setTablePrefix(new String[] { "t_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[]{"t_user"}); // 需要生成的表
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent(rb.getString("parent"));
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("domain");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-rb");
this.setMap(map);
}
};
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
// 调整 domain 生成目录演示
focList.add(new FileOutConfig("/templates/entity.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirBase")+ "/cn/ronghuanet/mybatisplus/domain/" + tableInfo.getEntityName() + ".java";
}
});
//query
focList.add(new FileOutConfig("/templates/query.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirBase")+ "/cn/ronghuanet/mybatisplus/query/" + tableInfo.getEntityName() + "Query.java";
}
});
// 调整 xml 生成目录演示
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirXml")+ "/cn/ronghuanet/mybatisplus/mapper/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
TemplateConfig tc = new TemplateConfig();
tc.setService("/templates/service.java.vm");
tc.setServiceImpl("/templates/serviceImpl.java.vm");
tc.setEntity(null);
tc.setMapper("/templates/mapper.java.vm");
//tc.setController(null);
tc.setXml(null);
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
mpg.setTemplate(tc);
// 执行生成
mpg.execute();
}
}
测试:生成代码,在那边启动并通过get请求测试
4 进阶
4.1 高级查询+分页
//高级查询+分页
@Test
public void testAdvanceQuery() throws Exception{
UserQuery query = new UserQuery();
query.setPage(1);
query.setRows(10);
query.setKeyword("zs");
Page<User> page = new Page<>(query.getPage(), query.getRows());
//page 分页条件
//高级查询条件
EntityWrapper<User> wrapper = new EntityWrapper<>();
if (StrUtil.isNotEmpty(query.getKeyword()))
wrapper.like("name",query.getKeyword());
userService.selectPage(page, wrapper);
System.out.println(page.getTotal());
System.out.println(page.getRecords());
}
4.2 高级查询+分页+关联查询
test
//高级查询+分页+关联查询
@Test
public void testAdvanceQuery02() throws Exception{
UserQuery query = new UserQuery();
query.setPage(1);
query.setRows(10);
query.setKeyword("");
//page 分页条件
//高级查询条件
PageList<User> pageList= userService.selectPageList(query);
System.out.println(pageList.getTotal());
System.out.println(pageList.getRows());
}
service
@Override
public PageList<User> selectPageList(UserQuery query) {
Page<User> page = new Page<>(query.getPage(), query.getRows());
//自定义mapper方法,返回关联数据对象
List<User> data = userMapper.loadPageList(page,query);
return new PageList<>(page.getTotal(),data);
}
mapepr.java
public interface UserMapper extends BaseMapper<User> {
List<User> loadPageList(Page<User> page, UserQuery query);
}
mapper.xml
<select id="loadPageList" resultMap="UserMap">
select u.*,d.id did,d.name dname
from t_user u left join t_department d
on u.department_id = d.id
</select>
<resultMap id="UserMap" type="cn.ronghuanet.gift.domain.User">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="department_id" property="departmentId" />
<association property="department" javaType="Department">
<id column="did" property="id" />
<result column="dname" property="name" />
</association>
</resultMap>
五 用户中心
1 用户中心需求分析
2 用户中心设计
3 用户中心功能实现概述
1)用户:
用户注册
完善用户信息
忘记密码:短信验证码
修改密码:原密码+验证码
用户实名认证提交
用户地址:crud
成长记录:crud
2)后台用户一些操作:
用户:禁用,启用 ,用户实名认证审核:阿里云身份证认证
成长记录:查看
用户地址:查看
====================
以上的功能其实都简单,除了注册要处理的业务逻辑要复杂都简单,只做注册
4 用户中心注册实现-手机号注册
4.1 需求分析与设计
4.1.1 需求分析
- 输入手机号完成
- 点击发送验证码(流程)
- 输入短信验证码
- 输入密码
- 提交注册
4.1.2 设计
1)表设计
2)流程设计
架构图:
发送短信验证码:
和上一个项目一样
注册流程图:
和上一个项目类似
不写前端,接口========
1)搭建用户微服务
2)用户服务写发送注册短信验证码接口
3) 注册
1校验
2 保存登陆信息返回loginid
3 保存用户信息
4 保存支付中心
6 发送注册成功的同志
4.1 发送短信验证码接口
4.1.1 basic common
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
util
package cn.ronghuanet.gift.util;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
/**
* 短信发送工具类
*/
public class SmsUtil {
/**
* 发送短信
* @param phones 手机们 a,b
* @param content 发送内容
* @return 返回值
*/
public static String sendSms(String phones,String content,String uid,String key){
PostMethod post = null;
try {
HttpClient client = new HttpClient();
post = new PostMethod("http://utf8.api.smschinese.cn");
post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf8");//在头文件中设置转码
NameValuePair[] data ={ new NameValuePair("Uid",uid),
new NameValuePair("Key",key),
new NameValuePair("smsMob",phones),
new NameValuePair("smsText",content)};
post.setRequestBody(data);
client.executeMethod(post);
int statusCode = post.getStatusCode();
System.out.println("statusCode:"+statusCode); //200 404 400
String result = new String(post.getResponseBodyAsString().getBytes("utf8"));
return result;
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (post != null) {
post.releaseConnection();
}
}
return null;
}
public static void main(String[] args) {
// System.out.println(SmsUtil
// .sendSms("17783849186", "您的验证码为:8848"));
}
}
4.1.2 用户服务
userController
@GetMapping("/register/{phone}")
public AjaxResult getSmsValidateCodeForRegister(@PathVariable("phone") String phone){
return userService.getSmsValidateCodeForRegister(phone);
}
userservice
@Autowired
private UserMapper userMapper;
@Override
public AjaxResult getSmsValidateCodeForRegister(String phone) {
// 判断是否注册过
RonghuaAssert.isNotBlank(phone,ErrorCode.ERROR_CODE_400);
List<User> userList = userMapper
.selectList(new EntityWrapper<User>().eq("phone", phone));
RonghuaAssert.isEmpty(userList, ErrorCode.ERROR_CODE_USER_EXSIT);
//发送短信验证码 codeservice
return validateCodeService
.getSmsValidateCodeForRegister(phone);
}
codeservice
@Service
public class IValidateCodeService implements cn.ronghuanet.gift.service.IValidateCodeService {
@Autowired
private RedisTemplate redisTemplate;
@Override
public AjaxResult getSmsValidateCodeForRegister(String phone) {
// 1 已经校验过
// 4 判断redis中是否已存在验证码 通过key去redis中获取
String obj = (String)redisTemplate.opsForValue()
.get("sms_register_verifycode_" + phone);
// 4.1 如果已存在 obj 验证码:发送时间
String smsVerifyCode = "";
if(StringUtils.isNotBlank(obj)){
smsVerifyCode = obj.split(":")[0]; // 验证码
Long sendTime = Long.parseLong(obj.split(":")[1]); // 发送时间
// 4.1.1 如果没过重发时间,就返回错误信息 重发时间:1分钟
if(System.currentTimeMillis() - sendTime < 60*1000){
throw new RuntimeException("请不要频繁发送验证码!");
}
}else{
// 4.2 如果不存在 要重新生成验证码,并且放入redis中
smsVerifyCode = VerifyCodeUtils.generateVerifyCode(6);
}
// 4.3 重新设置验证码的过期时间
String redisValue = smsVerifyCode+":"+System.currentTimeMillis();
redisTemplate.opsForValue().set("sms_register_verifycode_" +
phone,redisValue,5, TimeUnit.MINUTES );
// 5 发送短信
String smsContent = "您的验证码为:%s,请在%s分钟以内使用!";
// SmsUtil.sendSms(phone, String.format(smsContent, smsVerifyCode,5),
// UserConstants.UID,UserConstants.KEY);
System.out.println(String.format(smsContent, smsVerifyCode,5));
// 6 记录发送日志 @TODO
return AjaxResult.me();
}
}
4.2 注册接口
dto
@Data
public class UserPhoneRegisterDto {
@NotEmpty(message = "请输入手机号,在操作!")
private String phone;
@NotEmpty(message = "请输入手机验证码,在操作!")
private String validateCode;
@NotEmpty(message = "请输入密码,在操作!")
private String password;
}
usercontroller
@PostMapping("/register/phone")
public AjaxResult registerPhone( @Valid @RequestBody UserPhoneRegisterDto dto){
return userService.registerPhone(dto);
}
service
userserivce
@GlobalTransactional
@Override
public AjaxResult registerPhone(UserPhoneRegisterDto dto) {
//1 校验验证码
String inputValidateCode = dto.getValidateCode();
String validateCode = validateCodeService
.getSmsValidateCodeForRegister(dto.getPhone());
if (StringUtils.isEmpty(validateCode) ||
!inputValidateCode.equalsIgnoreCase(validateCode))
return AjaxResult.me().setSuccess(false).setMessage("请输入正确验证码!")
.setErrorCode(ErrorCode.ERROR_CODE_400.getCode());
//2 远程调用LoginClient完成loginUser添加返回loginId
LoginUser loginUser = new LoginUser();
loginUser.setUsername(UUID.randomUUID().toString());
loginUser.setPassword(dto.getPassword());
loginUser.setTel(dto.getPhone());
loginUser.setType(1);
AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
Long loginId = Long.valueOf(ajaxResult.getResultObj().toString());
//3 保存用户基本信息
User user = new User();
user.setCreateTime(new Date().getTime());
user.setPhone(dto.getPhone());
user.setPassword(dto.getPassword());
user.setSalt(null);
user.setBitState(1L);
user.setSecLevel(1);
user.setLoginId(loginId);
userMapper.insert(user);
//4 保存详情
UserInfo userInfo = new UserInfo();
userInfo.setRegTime(new Date().getTime());
userInfo.setLevel(0);
userInfo.setGrowScore(0);
userInfo.setUserId(user.getId());
userInfoMapper.insert(userInfo);
//5 发送注册成功通知 @TODO
return AjaxResult.me();
}
codeservice
@Override
public String getSmsValidateCodeForRegister(String phone) {
String codeStr = (String) redisTemplate.opsForValue().get("sms_register_verifycode_" +
phone);
if (StringUtils.isEmpty(codeStr))
return null;
return codeStr.split(":")[0];
}
六 用户中心后端微服务搭建
1 结构分析
2 springboot+mybatisplus+config-server+eureka
2.1 导入 jar
user-service
<dependencies>
<!--依赖需要数据库支持-->
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--自己公共代码-->
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-user-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
user-common
<dependencies>
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-basic</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--mybatisplusjar 不能直接导入starter,里面mybatisplus自动配置,
需要依赖于一些配置,这个模块并没有做mybatis相关配置,会报错!
只需要导入里面核心jar,让domain不报错而已
-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
core
<dependencies>
<!--依赖微服务所需jar-->
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--mybatisplusjar-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
service
<dependencies>
<dependency>
<groupId>cn.ronghuanet.gift</groupId>
<artifactId>gift-dependencies-basic</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Eureka 客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--configclient端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
2.2 配置
配置库
application-user-dev.yml
server:
port: 20010
spring:
application:
name: gift-user
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/gift_user
username: root
password: 123456
mybatis-plus:
type-aliases-package: cn.ronghuanet.gift.domain,cn.ronghuanet.gift.query
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10020/eureka/
instance:
prefer-ip-address: true #使用ip注册到Eureka
instance-id: gift-user:20010 #指定客户端实例的ID
bootsrap.yml
spring:
profiles:
active: dev #默认启动是dev
cloud:
config:
uri: http://127.0.0.1:10010 #配置服务器,相当于连上仓库曹
label: master #分支
name: application-user #gitee上面名称
profile: ${spring.profiles.active}
#环境 java -jar -d spring.profiles.active=test gift-eureak.jar
分页插件
略过
2.3 入口类
package cn.ronghuanet.gift;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("cn.ronghuanet.gift.mapper")
public class UserStart {
public static void main(String[] args) {
SpringApplication.run(UserStart.class,args);
}
}
2.4 测试
在eureka中能看到
生成代码在起动测试 get
3 集成网关
zuul的配置中心文件配置
routes:
ribbon:
eager-load.enabled: true # 饥饿加载
myUser.serviceId: gift-user #服务名
myUser.path: /user/** #哪个路径
4 集成knife4j
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名knife4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!其底层是对Springfox的封装,使用方式也和Springfox一致,只是对接口文档UI进行了优化。
姚桑教诲: 类似swagger,但是比它高级! 界面更漂亮,除了支持在线测试以外,还能导出离线文档!
4.1 微服务集成
gift-dependencies-service
<!-- 包含了ui界面 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!-- 2.x基于springfox2.x,3.x基于springfox3.x-->
<version>3.0.2</version>
</dependency>
配置
package cn.ronghuanet.gift.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2 //2.x用 @EnableSwagger2WebMvc
public class Knife4jConfig {
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("用户中心接口文档")
.description("用户中心接口文档,仅限内部使用")
.termsOfServiceUrl("http://www.yaosang.org")
.contact(new Contact("yaosang", "www.yaosang.org", "yaosang@qq.com"))
.version("1.0")
.build();
}
@Bean
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//分组名称
//.groupName("1.0版本")
.select()
//指定controller(接口)扫描的包路径
.apis(RequestHandlerSelectors.basePackage("cn.ronghuanet.gift.controller"))
.paths(PathSelectors.any())
.build();
}
}
4.2 网关集成-一辈子只做一次
zuul-service
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
package cn.ronghuanet.gift.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.List;
@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
@Autowired
private RouteLocator routeLocator;
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
//swaggerResource.setLocation(location+"?group=系统管理接口");
swaggerResource.setLocation(location);
//这个配置影响不大
swaggerResource.setSwaggerVersion("3.0");
return swaggerResource;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resourceList = new ArrayList<>();
//获取所有router
List<Route> routeList = routeLocator.getRoutes();
for (Route route:routeList) {
//排除不需要参与文档聚合的服务
if (!route.getId().equals("monitor-server")){
//第一个参数指定服务名,id是服务名 eg. order-server
//第二个参数指定该服务的文档访问接口 eg. /order-server/v2/api-docs。fullPath是该服务的路由地址 eg. /order-server/**
resourceList.add(swaggerResource(route.getId(), route.getFullPath()
.replace("/**", "/v2/api-docs")));
}
}
return resourceList;
}
}
5 整体步骤整理
创建微服务的步骤
1导入jar
common:
gift-dependencies-basic
mybatis-plus
service:
core(mybatisplus,mysql)-service(config,eureka,knife4j)-basic
common
2 配置
application-xxx-dev.yml
bootstrap
网关集成微服务
mybatisplus分页插件
knife4j配置
3入口类
@Springboot
@Eureka
@MapperScan
4 测试
Eureka
knife4j测试