SpringCloud分布式实现雷丰阳尚筹网—— 框架搭建与 登录(一)

SpringCloud实现雷风阳尚筹网笔记

1 尚筹网项目的新架构

p9在这里插入图片描述

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实体类

p10
在这里插入图片描述

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的依赖!

p11

  • 生成主启动类

@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
      # 表示提供给客户端进行注册服务的地址

测试:

数据添加一条数据

p13
在这里插入图片描述
先启动Eureka,再启动Provider

查看注册并测试


p14
在这里插入图片描述


p15
在这里插入图片描述

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 存放目录

p12
在这里插入图片描述

6.2 路径问题

  • static目录下的文件,部署到服务器上后会放在Web应用的根目录下,所以页面上路径根据是否配置了server.context-path,有两种情况:

  • 配置了server.context-path

    • /contextPath/xxx/xxx
  • 没有配置server.context-path

    • /xxx/xxx

特别注意:登录注册功能解析

p19
在这里插入图片描述

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主页连接地址

p16
在这里插入图片描述

@Controller
public class MemberController {
	
	@Autowired
	private MemberRemoteService memberRemoteService; 
	
	@RequestMapping("/member/toRegPage")
	public String toRegPage() {
		return "member/reg";
	}
}

整合member的页面到同一目录下

p17
在这里插入图片描述
修改样式路径

p18

在这里插入图片描述

8 注册功能

8.1 修改from表单

  • 添加method 方法 和 映射连接

20
在这里插入图片描述

  • 表单要提交的文本

p21
在这里插入图片描述

  • 修改超链接为提交按钮

p22
在这里插入图片描述

  • 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);
	}

猜你喜欢

转载自blog.csdn.net/weixin_42405670/article/details/84426075
今日推荐