day13【前台】搭建环境
1、会员系统架构
2、创建工程
2.1、工程清单
- 父工程、 聚合工程:
atcrowdfunding07-member-parent
(唯一的 pom 工程) - 注册中心:
atcrowdfunding08-member-eureka
- 实体类模块:
atcrowdfunding09-member-entity
MySQL
数据服务: atcrowdfunding10-member-mysql-provider
Redis
数据服务: atcrowdfunding11-member-redis-provider
- 会员中心:
atcrowdfunding12-member-authentication-consumer
- 项目维护:
atcrowdfunding13-member-project-consumer
- 订单维护:
atcrowdfunding14-member-order-consumer
- 支付功能:
atcrowdfunding15-member-pay-consumer
- 网关:
atcrowdfunding16-member-zuul
API
模块: atcrowdfunding17-member-api
2.2、创建工程
- 父工程:创建
Maven Project
,parent
工程打包方式为pom
- 其他工程:在
parent
下创建Maven Module
,打包方式均为jar
(SpringBoot
打包方式选择jar
包,则使用自带的Tomcat
)
2.3、工程结构
2.4、搭建环境约定
2.5、包名约定
- 主启动类所在的包:
com.atguigu.crowd
- 其他包都作为
com.atguigu.crowd
的子包
2.6、主启动类约定
2.7、端口号约定
atcrowdfunding08-member-eureka 1000
atcrowdfunding10-member-mysql-provider 2000
atcrowdfunding11-member-redis-provider 3000
atcrowdfunding12-member-authentication-consumer 4000
atcrowdfunding13-member-project-consumer 5000
atcrowdfunding14-member-order-consumer 7000
atcrowdfunding15-member-pay-consumer 8000
atcrowdfunding16-member-zuul 80
3、parent工程
3.1、依赖管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
</dependencies>
</dependencyManagement>
4、Eureka注册中心
4.1、引入依赖
- 在
Eureka
工程引入eureka-server
的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
4.2、创建主启动类
@EnableEurekaServer
注解:启用Eureka
服务器端功能
@EnableEurekaServer
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
4.3、创建yml配置文件
server:
port: 1000
spring:
application:
name: atguigu-crowd-eureka
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4.4、测试
- 访问:
http://localhost:1000/
5、entity工程
5.1、实体类的细分
5.2、创建包
- 在
entity
工程下创建
com.atguigu.crowd.entity.po
com.atguigu.crowd.entity.vo
6、lombok
6.1、lombok 原理
6.2、lombok安装
6.2.1、引入依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
6.2.2、lombok jar包
6.2.3、安装
- 双击运行
lombok.jar
,指定STS.exe
程序所在位置,然后执行安装(更新)
- 安装完成后,关注如下两个文件
- 多了一个
lombok.jar
文件,其实就是将lombok-1.18.8.jar
复制了一份,然后改了个名字 STS.ini
配置文件也被修改了
STS.ini
配置文件最后一行:指定lombok.jar
包所在的位置
-startup
plugins/org.eclipse.equinox.launcher_1.5.500.v20190715-1310.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.1100.v20190907-0426
-product
org.springsource.sts.ide
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.8
-Xms256m
-Xmx1024m
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.module.lock.timeout=10
-javaagent:D:\JavaTools\sts-bundle\sts-3.9.10.RELEASE\lombok.jar
6.3、lombok测试
6.3.1、注解
@Data
:每一个字段都加入getXxx()
、setXxx()
、toString()
方法@ToString
: toString()
方法@NoArgsConstructor
:无参构造器@AllArgsConstructor
:全部字段都包括的构造器@EqualsAndHashCode
:equals
和 hashCode
方法@Getter
- 类:所有字段都加入
getXxx()
方法 - 字段:当前字段加入getXxx()`方法
@Setter
- 类:所有字段都加入
setXxx()
方法 - 字段: 当前字段加入
setXxx()
方法
6.3.2、常用组合
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee{
6.3.3、常见问题
- 安装完成后,重启
STS
,如果按照安装说明正确安装,并且提示安装成功,重启后依然编译报错的话
- 将路径修改为相对路径:
-javaagent:lombok.jar
- 请右键
STS.exe
选择以管理员身份运行。
- 莫名其妙报错:注解删了,重新写一遍
7、mysql-provider工程
7.1、创建数据库表
CREATE TABLE t_member (
id INT (11) NOT NULL AUTO_INCREMENT,
loginacct VARCHAR (255) NOT NULL,
userpswd CHAR(200) NOT NULL,
username VARCHAR (255),
email VARCHAR (255),
authstatus INT (4) COMMENT '实名认证状态 0 - 未实名认证, 1 - 实名认证申请中, 2 - 已实名认证',
usertype INT (4) COMMENT '0 - 个人, 1 - 企业',
realname VARCHAR (255),
cardnum VARCHAR (255),
accttype INT (4) COMMENT '0 - 企业, 1 - 个体, 2 - 个人, 3 - 政府',
PRIMARY KEY (id)
) ;
7.2、逆向工程
- 借助
reverse
工程逆向生成,并把相应资源归位、
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="atguiguTables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/project_crowd"
userId="root" password="101713">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.entity">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.mapper">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetProject=".\src\main\java"
targetPackage="com.atguigu.crowd.mapper">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<table tableName="t_member" domainObjectName="MemberPO" />
</context>
</generatorConfiguration>
- 将实体类归位至
entity
工程下,MemberPO
实体类使用lombok
注解标记
@NoArgsConstructor
@AllArgsConstructor
@Data
public class MemberPO {
private Integer id;
private String loginacct;
private String userpswd;
private String username;
private String email;
private Integer authstatus;
private Integer usertype;
private String realname;
private String cardnum;
private Integer accttype;
- 将
Mapper
接口归位至mysql-provider
工程下(这步会报错,因为Mapper
接口需要用到entity
工程中的实体类,然而现在mysql-provider
工程并没有依赖entity
工程,添加以来之后报错就会消失)
- 将
Mapper.xml
映射文件归位至mysql-provider
工程下
7.3、引入依赖
- 添加相关依赖:
- 数据库相关依赖
- 需要对外暴露服务,添加
web
依赖 - 服务需要注册进
Eureka
里面,添加eureka-client
依赖 - 需要使用实体类和工具类,添加对
entity
工程和common-util
工程的依赖
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding09-member-entity</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding05-common-util</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
7.4、创建主启动类
@MapperScan("com.atguigu.crowd.mapper")
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
7.5、创建yml配置文件
- 配置端口号
- 配置微服务名称
- 配置数据源
- 指定
Eureka
注册中心的地址 - 指定
Mapper
映射文件的地址 - 修改局部日志级别
server:
port: 2000
spring:
application:
name: atguigu-crowd-mysql
datasource:
name: mydb
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/project_crowd?serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
mybatis:
mapper-locations: classpath*:/mybatis/mapper/*Mapper.xml
logging:
level:
com.atguigu.crowd.mapper: debug
com.atguigu.crowd.test: debug
7.6、测试Mapper
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyBatisTest {
@Autowired
private DataSource dataSource;
@Autowired
private MemberPOMapper memberPOMapper;
private Logger logger = LoggerFactory.getLogger(MyBatisTest.class);
@Test
public void testConnection() throws SQLException {
Connection connection = dataSource.getConnection();
logger.debug(connection.toString());
}
@Test
public void testMapper() {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String source = "123123";
String encode = passwordEncoder.encode(source);
MemberPO memberPO = new MemberPO(null, "jack", encode, "杰克", "jack@qq.com", 1, 1, "杰克", "123123", 2);
memberPOMapper.insert(memberPO);
}
}
2020-06-25 20:33:50.107 DEBUG 24484 --- [ main] com.atguigu.crowd.test.MyBatisTest : com.mysql.cj.jdbc.ConnectionImpl@f9cab00
7.7、api工程中暴露接口
7.7.1、引入依赖
- 在
api
工程中引入依赖
- 通过
feign
实现远程调用,则需要添加openfeign
依赖 - 需要使用实体类和工具类,添加对
entity
工程和common-util
工程的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding05-common-util</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding09-member-entity</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
7.7.2、创建接口
@FeignClient("atguigu-crowd-mysql")
public interface MySQLRemoteService {
@RequestMapping("/get/memberpo/by/login/acct/remote")
ResultEntity<MemberPO> getMemberPOByLoginAcctRemote(@RequestParam("loginacct") String loginacct);
}
7.8、provider中实现接口
7.8.1、创建Handler
- 在
mysql-provider
工程的Handler
中,实现远程调用接口
@RestController
public class MemberProviderHandler {
@Autowired
private MemberService memberService;
@RequestMapping("/get/memberpo/by/login/acct/remote")
public ResultEntity<MemberPO> getMemberPOByLoginAcctRemote(@RequestParam("loginacct") String loginacct) {
try {
MemberPO memberPO = memberService.getMemberPOByLoginAcct(loginacct);
return ResultEntity.successWithData(memberPO);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
}
7.8.2、创建Service
@Transactional(readOnly = true)
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberPOMapper memberPOMapper;
@Override
public MemberPO getMemberPOByLoginAcct(String loginacct) {
MemberPOExample example = new MemberPOExample();
Criteria criteria = example.createCriteria();
criteria.andLoginacctEqualTo(loginacct);
List<MemberPO> list = memberPOMapper.selectByExample(example);
if (list == null || list.size() == 0) {
return null;
}
return list.get(0);
}
}
7.9、测试mysql-provider
- 访问:
http://localhost:2000/get/memberpo/by/login/acct/remote?loginacct=jack
8、redis-provider工程
8.1、引入依赖
- 在
redis-provider
工程的pom
文件中引入相关依赖
redis starter
:整合Redis
- 需要对外暴露服务:
web
的依赖 - 需要注册进
Eureka
服务注册中心:eureka-client
的依赖 - 实体类和工具类的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding09-member-entity</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding05-common-util</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
8.2、创建主启动类
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
8.3、创建yml配置文件
- 指定
redis host
:redis
主机地址 - 端口号使用默认的
6379
server:
port: 3000
spring:
application:
name: atguigu-crowd-redis
redis:
host: 192.168.152.129
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
8.4、测试Redis
8.4.1、创建测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private StringRedisTemplate redisTemplate;
@Test
public void testSet() {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("apple", "red");
}
@Test
public void testExSet() {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("banana", "yellow", 5000, TimeUnit.SECONDS);
}
}
8.4.2、测试结果
8.5、api工程中暴露接口
- 设置永不超时的
key value
键值对 - 设置带超时的
key value
键值对 - 获取指定
key
的value
- 删除指定的
key
@FeignClient("atguigu-crowd-redis")
public interface RedisRemoteService {
@RequestMapping("/set/redis/key/value/remote")
ResultEntity<String> setRedisKeyValueRemote(
@RequestParam("key") String key,
@RequestParam("value") String value);
@RequestMapping("/set/redis/key/value/remote/with/timeout")
ResultEntity<String> setRedisKeyValueRemoteWithTimeout(
@RequestParam("key") String key,
@RequestParam("value") String value,
@RequestParam("time") long time,
@RequestParam("timeUnit") TimeUnit timeUnit);
@RequestMapping("/get/redis/string/value/by/key/remote")
ResultEntity<String> getRedisStringValueByKeyRemote(@RequestParam("key") String key);
@RequestMapping("/remove/redis/key/remote")
ResultEntity<String> removeRedisKeyRemote(@RequestParam("key") String key);
}
8.6、provider中实现接口
- 在
redis-provider
工程的Handler
中,实现远程调用接口
@RestController
public class RedisHandler {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping("/set/redis/key/value/remote")
ResultEntity<String> setRedisKeyValueRemote(
@RequestParam("key") String key,
@RequestParam("value") String value) {
try {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set(key, value);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
@RequestMapping("/set/redis/key/value/remote/with/timeout")
ResultEntity<String> setRedisKeyValueRemoteWithTimeout(
@RequestParam("key") String key,
@RequestParam("value") String value,
@RequestParam("time") long time,
@RequestParam("timeUnit") TimeUnit timeUnit) {
try {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set(key, value, time, timeUnit);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
@RequestMapping("/get/redis/string/value/by/key/remote")
ResultEntity<String> getRedisStringValueByKeyRemote(@RequestParam("key") String key) {
try {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
String value = operations.get(key);
return ResultEntity.successWithData(value);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
@RequestMapping("/remove/redis/key/remote")
ResultEntity<String> removeRedisKeyRemote(@RequestParam("key") String key) {
try {
redisTemplate.delete(key);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
}
8.7、测试redis-provider
http://localhost:3000/set/redis/key/value/remote?key=orange&value=orange
http://localhost:3000/set/redis/key/value/remote/with/timeout?key=peach&value=pink&time=5000&timeUnit=SECONDS
http://localhost:3000/get/redis/string/value/by/key/remote?key=orange
http://localhost:3000/remove/redis/key/remote?key=peach
9、auth工程
9.1、引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding17-member-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>
</dependencies>
9.2、创建主启动类
- 启用服务注册发现功能,这样才能找到
provider
哟~
@EnableDiscoveryClient
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
9.3、创建yml配置文件
server:
port: 4000
spring:
application:
name: atguigu-crowd-auth
thymeleaf:
prefix: classpath:/templates/
suffix: .html
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
9.4、创建Handler
@Controller
public class PortalHandler {
@RequestMapping("/")
public String showPortalPage() {
return "portal";
}
}
9.5、调整页面
9.5.1、添加静态资源
9.5.2、首页的小修小改
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<base th:href="@{/}"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/carousel.css">
9.6、测试
10、zuul工程
10.1、引入依赖
- 需要注册进
Eureka
里面:添加eureka-client
的依赖 - 网关当然要添加
zuul
的依赖咯~
<dependencies>
<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-zuul</artifactId>
</dependency>
</dependencies>
10.2、创建主启动类
@EnableZuulProxy
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
10.3、创建yml配置文件
- 端口号配置为
80
,访问时就不需要写端口号啦~ ignored-services: "*"
:忽略微服务的真实名称sensitive-headers: "*"
:重定向时保持原本头信息service-id: atguigu-crowd-auth
:访问zuul
网关微服务时转接至auth
微服务path: /**
:任意多层路径均可访问
server:
port: 80
spring:
application:
name: atguigu-crowd-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
zuul:
ignored-services: "*"
sensitive-headers: "*"
routes:
crowd-portal:
service-id: atguigu-crowd-auth
path: /**
10.4、配置域名
10.5、测试