个人博客网:https://wushaopei.github.io/ (你想要这里多有)
SpringCloud实现雷风阳尚筹网笔记
1 尚筹网项目的新架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u5cmQ4rQ-1584113384761)(images/p9.png)]
2 创建工程清单
ac-sc-parent
ac-sc-common
ac-sc-feign-api
ac-sc-eureka-reg-center
ac-sc-portal-provider
ac-sc-manager-provider
ac-sc-activiti-provider
ac-sc-protal-consumer
ac-sc-manager-consumer
3 项目基础设定
3.1 包名
- 主启动类所在包:com.webcode.ac.sc
- 实体类:com.webcode.ac.sc.entities
- 工具类:com.webcode.ac.sc.utils
- Mapper接口:com.webcode.ac.sc.mapper
- Service接口:com.webcode.ac.sc.service
- Service实现类:com.webcode.ac.sc.service.impl
- Controller类:com.webcode.ac.sc.controller
- 工厂类:com.webcode.ac.sc.factory
3.2 端口号
-
ac-sc-parent
不需要
-
ac-sc-common
不需要
-
ac-sc-feign-api
不需要
-
ac-sc-eureka-reg-center
10000
-
ac-sc-portal-provider
10001
-
ac-sc-manager-provider
10002
-
ac-sc-activiti-provider
10003
-
ac-sc-protal-consumer
80
-
ac-sc-manager-consumer
10004
4. t_member 表结构分析
字段作用 | 字段名称 | 字段类型 | 字段长度 |
---|---|---|---|
主键 | member_id | int | |
登录账号 | login_acc | varchar | 100 |
登录密码 | login_pwd | varchar | 100 |
欢迎信息中显示的昵称 | nick_name | varchar | 100 |
真实姓名 | real_name | varchar | 100 |
身份证号 | card_num | varchar | 100 |
手机号 | phone_num | varchar | 20 |
Email地址 | email_addr | varchar | 100 |
实名认证状态 | auth_status | tinyint | |
账户类型 | acc_type | tinyint | |
是否为企业账号 | company | tinyint | |
备用字段1 | extral_field_a | varchar | 300 |
备用字段2 | extral_field_b | varchar | 300 |
备用字段3 | extral_field_c | varchar | 300 |
备用字段4 | extral_field_d | varchar | 300 |
- sql数据库语句
CREATE TABLE `t_member` (
`member_id` int NOT NULL AUTO_INCREMENT ,
`login_acc` varchar(100) NULL ,
`login_pwd` varchar(100) NULL ,
`nick_name` varchar(100) NULL ,
`real_name` varchar(100) NULL ,
`card_num` varchar(100) NULL ,
`phone_num` varchar(20) NULL ,
`email_addr` varchar(100) NULL ,
`auth_status` tinyint NULL ,
`acc_type` tinyint NULL ,
`company` tinyint NULL ,
`extral_field_a` varchar(300) NULL ,
`extral_field_b` varchar(300) NULL ,
`extral_field_c` varchar(300) NULL ,
`extral_field_d` varchar(300) NULL ,
PRIMARY KEY (`member_id`)
)
5 加入SpringCloud环境
5.1 ac-parent
<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>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
5.2 ac-portal-provider工程
<dependency>
<groupId>com.atguigu.ac.springcloud</groupId>
<artifactId>ac-sc-feign-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 加入Eureka客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
导入或生成实体类
- 创建或导入三个相关实体类
public class Permission {
private Integer id;
private Integer pid;
//必须和zTree中使用的属性名一致
private String name;
//必须和zTree中使用的属性名一致
private String icon;
//必须和zTree中使用的属性名一致
private String url;
//必须和zTree中使用的属性名一致
private Boolean open = true;
//增加checked 来表是被选中的树形菜单的属性
private Boolean checked;
public class Role {
private Integer id;
private String name;
public class User {
private Integer id;
private String loginacct;
private String userpswd;
private String username;
private String email;
private String createtime;
- 逆向工程生成member实体类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgmjuHjL-1584113384768)(images/p10.png)]
public class Member {
private Integer memberId;
private String loginAcc;
private String loginPwd;
private String nickName;
private String realName;
private String cardNum;
............................省略不写
生成相应的 无参、有参构造、toString方法。
-
调整 mapper.xml中的包名和逆向生成实体类的包名,并分别复制实体类到common 和 protal-provider两个工程下。
-
为protal-provider可以使用Mappermapper,给它添加对 Common的依赖!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGK7V25c-1584113384769)(images/p11.png])
- 生成主启动类
@SpringBootApplication //声明当前类为SpringBoot的主服务类
@EnableEurekaClient //声明当前为Eureka的客户端
@MapperScan("com.webcode.ac.sc.mapper") //扫描Mapper文件
public class PortalProviderMainType {
public static void main(String[] args) {
SpringApplication.run(PortalProviderMainType.class, args);
}
}
- Service 类
接口类
package com.webcode.ac.sc.service;
public interface MemberService {
int removeByPrimaryKey(Integer memberId);
int save(Member record);
Member getByPrimaryKey(Integer memberId);
List<Member> getAll();
int updateByPrimaryKey(Member record);
}
实现类
package com.webcode.ac.sc.service.impl;
@Service
@Transactional(readOnly=true) //声明当前类的内容为只读
public class MemberServiceImpl implements MemberService{
@Autowired
private MemberMapper memberMapper;
@Override //由于当前方法需要操作数据库获取数据,修改权限为false,并配置事务的类型为执行独立的事务,又由于当前方法为删除数据的操作,可能会存在失败等异常现象,所以配置回滚数据,同时抛异常
@Transactional(readOnly=false,rollbackFor=Exception.class,propagation=Propagation.REQUIRES_NEW)
public int removeByPrimaryKey(Integer memberId) {
return memberMapper.deleteByPrimaryKey(memberId);
}
@Override //由于当前方法需要操作数据库获取数据,修改权限为false,并配置事务的类型为执行独立的事务
@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)
public int save(Member record) {
return memberMapper.insert(record);
}
@Override
public Member getByPrimaryKey(Integer memberId) {
return memberMapper.selectByPrimaryKey(memberId);
}
@Override
public List<Member> getAll() {
return memberMapper.selectAll();
}
@Override //由于当前方法需要操作数据库获取数据,修改权限为false,并配置事务的类型为执行独立的事务
@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)
public int updateByPrimaryKey(Member record) {
return memberMapper.updateByPrimaryKey(record);
}
}
- handler 方法
@RestController
public class getMemberById {
@Autowired
private MemberService memberService;
//根据id查找用户信息
@RequestMapping("/portal/provider/member/{id}")
public ResultEntity<Member> getMemberById(@PathVariable("id") Integer id){
Member member = memberService.getByPrimaryKey(id);
return new ResultEntity<Member>(ResultEntity.SUCCESS,ResultEntity.NO_MSG,member);
}
}
- 配置 application.yml
server:
port: 10001
spring:
application:
name: ProtalProvider
datasource:
name: druid-source
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://127.0.0.1:3306/springcloud?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8
username: root
password: root
dbcp2:
min-idle: 5
initial-size: 5
max-total: 5
max-wait-millis: 200
mybatis:
mapper-locations: classpath:mappers/*Mapper.xml
eureka:
client:
service-url:
defaultZone: http://localhost:10000/eureka
# 这里是去注册服务的注册中心的地址,当前服务到中心注册服务,然后被客户端请求调用
5.3 ac-eureka-reg-center
pom.xml依赖
<dependencies>
<!-- eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
主启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaRegCentMainType {
public static void main(String[] args) {
SpringApplication.run(EurekaRegCentMainType.class, args);
}
}
application.yml配置文件
server:
port: 10000 # 注册中心端口号
eureka:
instance:
hostname: localhost #注册中心ip
client:
register-with-eureka: false #表示我是注册中心自己,不在当前注册中心注册
fetch-registry: false #表示我不是调用服务的
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
# 表示提供给客户端进行注册服务的地址
测试:
数据添加一条数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHRqp17Z-1584113384771)(images/p13.png)]
先启动Eureka,再启动Provider
查看注册并测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-38HP0nOs-1584113384775)(images/p14.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHHtoNTG-1584113384777)(images/p15.png)]
5.4 ac-portal-Consummer
application.yml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- eureka-server客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- 主启动器
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PotalConsummerMainType {
public static void main(String[] args) {
SpringApplication.run(PotalConsummerMainType.class, args);
}
}
- application.yml
server:
port: 80
spring:
application:
name: PortalConsummer
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:10000/eureka
6 静态资源
6.1 存放目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wI0RIK4G-1584113384780)(images/p12.png)]
6.2 路径问题
-
static目录下的文件,部署到服务器上后会放在Web应用的根目录下,所以页面上路径根据是否配置了server.context-path,有两种情况:
-
配置了server.context-path
- /contextPath/xxx/xxx
-
没有配置server.context-path
- /xxx/xxx
特别注意:登录注册功能解析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3lYHZbU-1584113384781)(images/p19.png)]
7 进入首页
7.1 Controller映射转发首页
- Controller跳转到首页
@Controller
public class IndexController {
//跳转到首页
@RequestMapping("/index")
public String toIndexPage() {
//templates/index.ftl
return "index";
}
}
7.2. 远程访问服务接口
- ac-sc-feign-Api
- 远程访问接口
@FeignClient(value="ProtalProvider")//将当前包扫描用于访问远程服务
public interface MemberRemoteService {
@RequestMapping("/portal/provider/member/register")
public ResultEntity<String> doRegisterRemote(@RequestBody Member member);
}
7.3 进入用户注册页面
a.修改main主页连接地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NsygC4hO-1584113384783)(images/p16.png)]
@Controller
public class MemberController {
@Autowired
private MemberRemoteService memberRemoteService;
@RequestMapping("/member/toRegPage")
public String toRegPage() {
return "member/reg";
}
}
整合member的页面到同一目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QptjwmSS-1584113384785)(images/p17.png)]
修改样式路径
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rIu5kfxd-1584113384787)(images/p18.png)]
8 注册功能
8.1 修改from表单
- 添加method 方法 和 映射连接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAF58FWg-1584113384787)(images/p20.png)]
- 表单要提交的文本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R8zjIL7f-1584113384790)(images/p21.png)]
- 修改超链接为提交按钮
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zY8UF3k-1584113384792)(images/p22.png)]
- SCMS-sc-portal-Consummer
当前方法通过远程调用Provider所注册的服务获取对数据库的操作,从而获取表单数据提交的结果,并进行跳转到登录页面!
@Autowired
private MemberRemoteService memberRemoteService;
//获取表单提交数据,保存导数据库
@RequestMapping("/member/doRegister")
public String doRegister(Member member,Model model) {
//doRegisterRemote方法会进行远程调用注册中心的“ProtalProvider”的服务,来进行查询
ResultEntity<String> resultEntity = memberRemoteService.doRegisterRemote(member);
String result = resultEntity.getResult();
if(ResultEntity.SUCCESS.equals(result)) {
return "member/login";
}
if(ResultEntity.FAILED.equals(result)) {
String message = resultEntity.getMessage();
model.addAttribute(ACConst.MESSAGE_ATTR_NAME, message);
return "member/reg";
}
System.err.println(member);
return "member/reg";
}
- SCMS-sc-portal-Provider
当前方法接收远程调用接口在注册中心的请求,并通过已注册的服务找到当前方法,传递表单数据,通过当前handler方法执行对数据库的检测,根据检测结果执行注册或重复提示,并返回json数据到请求端。
@Autowired
private MemberService memberService;
@RequestMapping("/portal/provider/member/register")
public ResultEntity<String> doRegisterRemote(@RequestBody Member member){
//1.准备resultEntity 对象
ResultEntity<String> resultEntity = new ResultEntity<>();
//2.获取登录账号数据
String loginAcc = member.getLoginAcc();
try {
//3.检测登录账号是否被占用
int count = memberService.getMemberLoginAcctCount(loginAcc);
if(count == 0) {
//4.如果没有被占用,执行保存
memberService.save(member);
//5.如果保存成功,则设置执行结果为成功
resultEntity.setResult(ResultEntity.SUCCESS);
}else {
//6.如果账号被占用,则设置为失败
resultEntity.setResult(ResultEntity.FAILED);
resultEntity.setMessage(ACConst.MESSAGE_LOGIN_FAILED);
}
} catch (Exception e) {
e.printStackTrace();
//7.如果上述操作抛出异常,则设置执行结果为失败
resultEntity.setData(ResultEntity.FAILED);
resultEntity.setMessage(e.getMessage());
}
//8.无论是否成功,都不需要返回数据
resultEntity.setData(ResultEntity.NO_DATA);
return resultEntity;
}
- 底层用户注册信息的加密
- 仅限于注册成功的情况
@Override
@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)
public int save(Member record) {
//获取传入的参数
String loginPwd = record.getLoginPwd();
//将传入的传输进行加密
String md5 = StringUtils.md5(loginPwd);
//初始密码修改为加密后的密码
record.setLoginPwd(loginPwd);
return memberMapper.insert(record);
}