1. 走进电商

1.1 电商行业分析

近年来,世界经济正向数字化转型,大力发展数字经济成为全球共识。党的十九大报告明确提出要建设“数字中国”“网络强国”,我国数字经济发展进入新阶段,市场规模位居全球第二,数字经济与实体经济深度融合,有力促进了供给侧结构性改革。电子商务是数字经济的重要组成部分,是数字经济最活跃、最集中的表现形式之一。
我国电子商务交易规模继续扩大,全国电子商务交易额达保持高速增长。国家统计局数据显示,2017年29.16万亿元,2018年31.64万亿元,2019年34.81万亿元,2020年交易额达38.21万亿元。
最近几年天猫双十一成交额

1.2 主要电商模式

  • B2B
    B2B ( Business to Business)是指进行电子商务交易的供需双方都是商家(或企业、公司),她(他)们使用了互联网的技术或各种商务网络平台,完成商务交易的过程。电子商务是现代 B2B marketing的一种具体主要的表现形式。
    案例:阿里巴巴、慧聪网

  • C2C
    C2C即 Customer(Consumer) to Customer(Consumer),意思就是消费者个人间的电子商务行为。比如一个消费者有一台电脑,通过网络进行交易,把它出售给另外一个消费者,此种交易类型就称为C2C电子商务。
    案例:淘宝、易趣、瓜子二手车

  • B2C
    B2C是Business-to-Customer的缩写,而其中文简称为“商对客”。“商对客”是电子商务的一种模式,也就是通常说的直接面向消费者销售产品和服务商业零售模式。这种形式的电子商务一般以网络零售业为主,主要借助于互联网开展在线销售活动。B2C即企业通过互联网为消费者提供一个新型的购物环境——网上商店,消费者通过网络在网上购物、网上支付等消费行为。
    案例:唯品会、乐蜂网

  • C2B
    C2B(Consumer to Business,即消费者到企业),是互联网经济时代新的商业模式。这一模式改变了原有生产者(企业和机构)和消费者的关系,是一种消费者贡献价值(Create Value), 企业和机构消费价值(Consume Value)。

C2B模式和我们熟知的供需模式(DSM, Demand SupplyModel)恰恰相反,真正的C2B 应该先有消费者需求产生而后有企业生产,即先有消费者提出需求,后有生产企业按需求组织生产。通常情况为消费者根据自身需求定制产品和价格,或主动参与产品设计、生产和定价,产品、价格等彰显消费者的个性化需求,生产企业进行定制化生产。
案例:海尔商城、 尚品宅配

  • O2O
    O2O即Online To Offline(在线离线/线上到线下),是指将线下的商务机会与互联网结合,让互联网成为线下交易的平台,这个概念最早来源于美国。O2O的概念非常广泛,既可涉及到线上,又可涉及到线下,可以通称为O2O。主流商业管理课程均对O2O这种新型的商业模式有所介绍及关注。
    案例:美团、饿了吗

  • B2B2C
    B2B2C是一种电子商务类型的网络购物商业模式,B是BUSINESS的简称,C是CUSTOMER的简称,第一个B指的是商品或服务的供应商,第二个B指的是从事电子商务的企业,C则是表示消费者。

案例:京东商城、天猫商城

  • 注:《畅购电商系统开发》采用B2C模式

2. 畅购前台-需求分析与系统设计

  • 电商项目分为:前台和后台
  • 前台:提供用户使用
  • 后台:提供商家进行管理

2.2 系统设计

2.2.1 技术架构

3. 架构搭建

3.1 后端环境

3.2.1 父工程:changgou4_parent_ali

  • 修改pom.xml文件,确定spring boot、spring cloud、spring cloud Alibaba 等版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.czxy.changgou</groupId><artifactId>changgou4-parent-ali</artifactId><packaging>pom</packaging><version>1.0-SNAPSHOT</version><modules><module>changgou4_common</module><module>changgou4_common_auth</module><module>changgou4_common_db</module><module>changgou4_gateway</module><module>changgou4_pojo</module><module>changgou4_service_web</module></modules><!-- 1 确定spring boot的版本--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version></parent><!--2  确定版本--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><spring-cloud-release.version>Hoxton.SR3</spring-cloud-release.version><nacos.version>1.1.0</nacos.version><alibaba.cloud.version>2.2.1.RELEASE</alibaba.cloud.version><mysql.version>5.1.32</mysql.version><mybatis.plus.version>3.4.0</mybatis.plus.version><druid.starter.version>1.1.9</druid.starter.version><jwt.jjwt.version>0.9.0</jwt.jjwt.version><jwt.joda.version>2.9.7</jwt.joda.version><swagger.version>2.7.0</swagger.version><beanutils.version>1.9.3</beanutils.version><aliyun.sdk.core.version>3.3.1</aliyun.sdk.core.version><aliyun.sdk.dysmsapi.version>1.0.0</aliyun.sdk.dysmsapi.version><changgou4.common.version>1.0-SNAPSHOT</changgou4.common.version><changgou4.common.auth.version>1.0-SNAPSHOT</changgou4.common.auth.version><changgou4.common.db.version>1.0-SNAPSHOT</changgou4.common.db.version><changgou4.pojo.version>1.0-SNAPSHOT</changgou4.pojo.version></properties><!-- 3 锁定版本--><dependencyManagement><dependencies><!-- sprig cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud-release.version}</version><type>pom</type><scope>import</scope></dependency><!--nacos --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>${nacos.version}</version></dependency><!--nacos cloud 发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${alibaba.cloud.version}</version></dependency><!--nacos cloud 配置 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${alibaba.cloud.version}</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>${alibaba.cloud.version}</version></dependency><!-- mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis.plus.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-annotation</artifactId><version>${mybatis.plus.version}</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- druid启动器 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.starter.version}</version></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${swagger.version}</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${swagger.version}</version></dependency><!--jwt--><!--JavaBean工具类,用于JavaBean数据封装--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>${beanutils.version}</version></dependency><!--jwt工具--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jwt.jjwt.version}</version></dependency><!--joda 时间工具类 --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>${jwt.joda.version}</version></dependency><!--短信--><dependency><groupId>com.aliyuncs</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>${aliyun.sdk.core.version}</version></dependency><dependency><groupId>com.aliyuncs.dysmsapi</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>${aliyun.sdk.dysmsapi.version}</version></dependency><!--自定义项目--><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_common</artifactId><version>${changgou4.common.version}</version></dependency><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_common_auth</artifactId><version>${changgou4.common.auth.version}</version></dependency><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_common_db</artifactId><version>${changgou4.common.db.version}</version></dependency><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_pojo</artifactId><version>${changgou4.pojo.version}</version></dependency></dependencies></dependencyManagement></project>

3.2.2 公共项目(基础):changgou4-common

  • 通用工具项目

  • 基于spring cloud开发基本依赖

  • web开发常见的工具类

  • 步骤一:修改pom.xml文件,添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>changgou4-parent-ali</artifactId><groupId>com.czxy.changgou</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>changgou4-common</artifactId><dependencies><!--短信--><dependency><groupId>com.aliyuncs</groupId><artifactId>aliyun-java-sdk-core</artifactId></dependency><dependency><groupId>com.aliyuncs.dysmsapi</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>
  • 步骤二:拷贝工具类

3.2.3 公共项目(认证):changgou4-common-auth

  • 认证通用工具项目

  • 步骤一:修改pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>changgou4-parent-ali</artifactId><groupId>com.czxy.changgou</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>changgou4-common-auth</artifactId><dependencies><!--通用基础--><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_common</artifactId></dependency><!--JavaBean工具类,用于JavaBean数据封装--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId></dependency><!--jwt工具--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><!--joda 时间工具类 --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency></dependencies></project>
  • 步骤二:拷贝工具类

3.2.4 公共项目(数据库):changgou4-common-db

  • 数据库通用工具项目

  • 步骤一:修改pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>changgou4-parent-ali</artifactId><groupId>com.czxy.changgou</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>changgou4-common-db</artifactId><dependencies><!--通用基础--><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4-common</artifactId></dependency><!-- mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- druid启动器 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency></dependencies></project>
  • 步骤二:配置类
  • 要求所有的服务项目包名必须是“com.czxy.changgou4”,否则配置无法扫描,就需要每个项目单独拷贝。


3.2.5 POJO项目:changgou4-pojo
 统一管理所有的JavaBean

 修改pom.xml文件

org.projectlombok
lombok

org.springframework.boot
spring-boot-starter-json

com.baomidou
mybatis-plus-annotation

3.2.6 网关:changgou4-gateway

  • 修改pom.xml文档
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>changgou4-parent-ali</artifactId><groupId>com.czxy.changgou</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>changgou4-gateway</artifactId><dependencies><!--自定义项目--><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4-common-auth</artifactId></dependency><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4-pojo</artifactId></dependency><!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies></project>
  • 创建application.yml文档
#端口号
server:port: 10010
spring:application:name: changgou4-gatewayservlet:multipart:max-file-size: 2MB    #上传文件的大小cloud:nacos:discovery:server-addr: 127.0.0.1:8848   #nacos服务地址gateway:discovery:locator:enabled: true               #开启服务注册和发现的功能,自动创建router以服务名开头的请求路径转发到对应的服务lowerCaseServiceId: true    #将请求路径上的服务名配置为小写
  • 拷贝跨域配置类 GlobalCorsConfig

package com.czxy.changgou4.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;@Configuration
public class GlobalCorsConfig {@Beanpublic WebFilter corsFilter2() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();if (CorsUtils.isCorsRequest(request)) {HttpHeaders requestHeaders = request.getHeaders();ServerHttpResponse response = ctx.getResponse();HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();HttpHeaders headers = response.getHeaders();headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,requestHeaders.getAccessControlRequestHeaders());if (requestMethod != null) {headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());}headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");if (request.getMethod() == HttpMethod.OPTIONS) {response.setStatusCode(HttpStatus.OK);return Mono.empty();}}return chain.filter(ctx);};}}
  • 创建启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
@EnableDiscoveryClient
public class CGGatewayApplication {public static void main(String[] args) {SpringApplication.run(CGGatewayApplication.class, args );}
}

3.3 前端环境

3.3.1 构建项目:changgou4-fore

  • 步骤一:使用脚手架构建项目
    npx create-nuxt-app changgou4-fore

  • 步骤二:npm打包方式、axios第三方模块、SSR渲染模式

3.3.2 整合axios

  • 步骤一:创建~/plugins/apiclient.js文件
  • 步骤二:编写nuxt整合模板,用于统一管理ajax请求路径
const request = {test : ()=> {return axios.get('/test')}
}var axios = null
export default ({ $axios, redirect }, inject) => {//赋值axios = $axios//4) 将自定义函数交于nuxt// 使用方式1:在vue中,this.$request.xxx()// 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()inject('request', request)
}
  • 步骤三:配置apiclient.js插件,修改nuxt.conf.js配置文件完成操作
  plugins: [{ src: '~plugins/apiclient.js'}],
  • 步骤四:修改nuxt.conf.js配置文件,配置axios通用设置
  axios: {baseURL: 'http://localhost:10010'},
  • 步骤五:测试 apiclient.js是否配置成功,访问test时,出现404
  async mounted() {let { data } = await this.$request.test()console.info(data)},

3.3.3 拷贝静态资源

  • 将所有静态资源拷贝到static目录中
  • 通过浏览器访问静态页面

3.3.4 修改Nuxt项目默认项

  • 1 修改默认布局,删除已有样式

  • 2 删除pages目录下的所有内容

3.3.5 配置公共js和css

  • 修改默认布局,添加公共js和css
<template><div><nuxt /></div>
</template><script>
export default {head: {title: '首页',link: [{rel:'stylesheet',href: '/style/base.css'},{rel:'stylesheet',href: '/style/global.css'},{rel:'stylesheet',href: '/style/header.css'},{rel:'stylesheet',href: '/style/footer.css'}],script: [{ type: 'text/javascript', src: '/js/jquery-1.8.3.min.js' }]}
}
</script><style></style>

4. 用户模块(8081)

4.1 搭建环境

4.1.1 后端web服务:changgou4-service-web

  • 修改pom.xml文档
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>changgou4-parent-ali</artifactId><groupId>com.czxy.changgou</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>changgou4_service_web</artifactId><dependencies><!--自定义项目--><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_common_db</artifactId></dependency><dependency><groupId>com.czxy.changgou</groupId><artifactId>changgou4_pojo</artifactId></dependency><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos 客户端 --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency></dependencies></project>
  • 创建application.yml文档
#端口号
server:port: 8081spring:application:name: web-service          #服务名datasource:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/changgou_db?useUnicode=true&characterEncoding=utf8username: rootpassword: 1234druid:    #druid 连接池配置initial-size: 1       #初始化连接池大小min-idle: 1           #最小连接数max-active: 20        #最大连接数test-on-borrow: true  #获取连接时候验证,会影响性能redis:database:   0host: 127.0.0.1port: 6379cloud:nacos:discovery:server-addr: 127.0.0.1:8848   #nacos服务地址sentinel:transport:dashboard: 127.0.0.1:8080
  • 创建启动类
package com.czxy.changgou4;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
@EnableDiscoveryClient
public class Web-serviceApplication {public static void main(String[] args) {SpringApplication.run( Web-serviceApplication.class , args );}
}

4.1.2 后端创建JavaBean:User

  • 在changgou4-pojo项目中添加User对象
package com.czxy.changgou4.pojo;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.beans.Transient;
import java.util.Date;/**  与数据库对应JavaBean* Created by liangtong.*/
@TableName("tb_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {/*CREATE TABLE `tb_user` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`created_at` timestamp NULL DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL,`email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Email',`mobile` varchar(20) COLLATE utf8_unicode_ci NOT NULL COMMENT '手机号码',`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '昵称',`password` char(60) COLLATE utf8_unicode_ci NOT NULL COMMENT '密码',`face` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '头像',`expriece` int(10) unsigned DEFAULT '0' COMMENT '经验值',PRIMARY KEY (`id`),UNIQUE KEY `users_mobile_unique` (`mobile`),UNIQUE KEY `users_name_unique` (`name`),UNIQUE KEY `users_email_unique` (`email`)) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci*/@TableId(value="id",type = IdType.AUTO)private Long id;@TableField(value="username")private String username;@TableField(value="password")private String password;@TableField(value="face")private String face;@TableField(value="expriece")private Integer expriece;@TableField(value="email")private String email;@TableField(value="mobile")private String mobile;@TableField(value="created_at")private Date createdAt;@TableField(value="updated_at")private Date updatedAt;@TableField(exist = false)private String code;@TableField(exist = false)private String password_confirm;}

4.1.3 前端页面:创建公共组件

  • 1 删除components目录下所有内容,并创建3个新组件

  • 2)创建 TopNav.vue组件,用于配置“顶部导航”
<template><!-- 顶部导航 start --><div class="topnav"><div class="topnav_bd w990 bc"><div class="topnav_left"></div><div class="topnav_right fr"><ul><li>您好,欢迎来到畅购![<a href="login.html">登录</a>] [<a href="register.html">免费注册</a>] </li><li class="line">|</li><li>我的订单</li><li class="line">|</li><li>客户服务</li></ul></div></div></div><!-- 顶部导航 end -->
</template><script>
export default {}
</script><style></style>
  • 3 创建 HeaderLogo.vue组件,用于配置“页面头部,仅有LOGO”
<template><!-- 页面头部 start --><div class="header w990 bc mt15"><div class="logo w990"><h2 class="fl"><a href="index.html"><img src="/images/logo.png" alt="畅购商城"></a></h2></div></div><!-- 页面头部 end -->
</template><script>
export default {}
</script><style></style>
  • 4)创建 Footer.vue组件,用于配置“底部版权”
<template><!-- 底部版权 start --><div class="footer w1210 bc mt15"><p class="links"><a href="">关于我们</a> |<a href="">联系我们</a> |<a href="">人才招聘</a> |<a href="">商家入驻</a> |<a href="">千寻网</a> |<a href="">奢侈品网</a> |<a href="">广告服务</a> |<a href="">移动终端</a> |<a href="">友情链接</a> |<a href="">销售联盟</a> |<a href="">畅购论坛</a></p><p class="copyright">© 2006-2020 畅购网上商城 版权所有,并保留所有权利。  ICP备案证书号:京ICP证070359号</p><p class="auth"><a href=""><img src="/images/xin.png" alt="" /></a><a href=""><img src="/images/kexin.jpg" alt="" /></a><a href=""><img src="/images/police.jpg" alt="" /></a><a href=""><img src="/images/beian.gif" alt="" /></a></p></div><!-- 底部版权 end -->
</template><script>
export default {}
</script><style></style>

4.2 用户注册:用户名占用

4.2.1 接口

http://localhost:10010/web-service/user/checkusername

4.2.2 后端

  • 创建三层需要的接口或类
  • 步骤一:创建UserMapper,编写findByUsername()完成“通过用户名查询用户”
package com.czxy.changgou4.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends BaseMapper<User> {/*** 通过用户名查询* @param username* @return*/@Select("select * from tb_user where username = #{username}")User findByUsername(@Param("username") String username);
}
  • 步骤二:创建UserService接口,查询功能
package com.czxy.changgou4.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.User;public interface UserService extends IService<User> {/*** 通过用户名查询* @param username* @return*/public User findByUsername(String username);
}
  • 步骤三:创建UserServiceImpl实现类,查询功能
package com.czxy.changgou4.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.UserMapper;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;/*** @author zzllforever*  */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic User findByUsername(String username) {return baseMapper.findByUsername(username);}
}
  • 步骤四:创建UserController,完成用户名检查
package com.czxy.changgou4.controller;import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.service.UserService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** Created by  .*/
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@PostMapping("/checkusername")public BaseResult checkUsername(@RequestBody User user){//查询用户User findUser = userService.findByUsername( user.getUsername() );//判断if(findUser != null){return BaseResult.error("用户名已经存在");} else {return BaseResult.ok("用户名可用");}}}

4.2.3 前端

  • 步骤一:创建Register.vue
  • 步骤二:添加公共组件
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户注册'},components : {TopNav,HeaderLogo,Footer}
}
</script><style></style>
  • 步骤三:编写注册表单,并导入独有样式
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><!-- 登录主体部分start --><div class="login w990 bc mt10 regist"><div class="login_hd"><h2>用户注册</h2><b></b></div><div class="login_bd"><div class="login_form fl"><form action="" method="post"><ul><li><label for="">用户名:</label><input type="text" class="txt" name="username" /><p>3-20位字符,可由中文、字母、数字和下划线组成</p><p class="error">用户名已存在</p></li><li><label for="">密码:</label><input type="password" class="txt" name="password" /><p>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号</p></li><li><label for="">确认密码:</label><input type="password" class="txt" name="password" /><p>请再次输入密码</p></li><li><label for="">手机号码:</label><input type="text" class="txt"  name="mobile" /><p>请输入手机号码</p></li><li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode" /><button >发送验证码<span>5秒</span></button></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb" checked="checked" /> 我已阅读并同意《用户注册协议》</li><li><label for="">&nbsp;</label><input type="submit" value="" class="login_btn" /></li></ul></form></div><div class="mobile fl"><h3>手机快速注册</h3><p>中国大陆手机用户,编辑短信 “<strong>XX</strong>”发送到:</p><p><strong>1069099988</strong></p></div></div></div><!-- 登录主体部分end --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户注册',link: [{rel:'stylesheet',href:'style/login.css'}],script: [{ type: 'text/javascript', src: 'js/header.js' },{ type: 'text/javascript', src: 'js/index.js' },]},components : {TopNav,HeaderLogo,Footer}
}
</script><style></style>
  • 步骤四:修改api.js,编写检查用户名的ajax函数
const request = {test : ()=> {return axios.get('/test')},//检查用户名checkUsername : ( username )=> {return axios.post('/web-service/user/checkusername', { username })}
}
  • 步骤五:修改Register.vue页面,完成检查功能
  • 发送ajax进行用户名是否可用检查
  • 如果可用,显示对应信息,并使用success样式显示
  • 如果不可用,显示对应信息,并使用error样式提示
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><!-- 登录主体部分start --><div class="login w990 bc mt10 regist"><div class="login_hd"><h2>用户注册</h2><b></b></div><div class="login_bd"><div class="login_form fl"><form action="" method="post"><ul><li><label for="">用户名:</label><input type="text" class="txt" name="username" v-model="user.username" @blur="checkUsernameFn" /><p>3-20位字符,可由中文、字母、数字和下划线组成</p><p :class="userMsg.usernameData.code == 1 ? 'success' : 'error'">{{userMsg.usernameData.message}} </p></li><li><label for="">密码:</label><input type="password" class="txt" name="password" /><p>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号</p></li><li><label for="">确认密码:</label><input type="password" class="txt" name="password" /><p>请再次输入密码</p></li><li><label for="">手机号码:</label><input type="text" class="txt"  name="mobile" /><p>请输入手机号码</p></li><li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode" /><button >发送验证码<span>5秒</span></button></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb" checked="checked" /> 我已阅读并同意《用户注册协议》</li><li><label for="">&nbsp;</label><input type="submit" value="" class="login_btn" /></li></ul></form></div><div class="mobile fl"><h3>手机快速注册</h3><p>中国大陆手机用户,编辑短信 “<strong>XX</strong>”发送到:</p><p><strong>1069099988</strong></p></div></div></div><!-- 登录主体部分end --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户注册',link: [{rel:'stylesheet',href:'style/login.css'}],script: [{ type: 'text/javascript', src: 'js/header.js' },{ type: 'text/javascript', src: 'js/index.js' },]},components : {TopNav,HeaderLogo,Footer},data() {return {user : {          //表单绑定对象username : ""},userMsg : {        //错误信息usernameData : ""}}},methods: {async checkUsernameFn() {let {data} = await this.$request.checkUsername( this.user.username )this.userMsg.usernameData = data}},
}
</script><style></style>

4.3 用户注册:手机号检查

4.3.1 接口

http://localhost:10010/web-service/user/checkmobile
4.3.2 后端

  • 步骤一:修改UserService,添加 findByMobile() 方法,进行电话号码的查询
/*** 通过手机号查询* @param mobile* @return*/
User findByMobile(String mobile);  步骤二:编写UserServiceImpl,实现findByMobile() 方法
@Override
public User findByMobile(String mobile) {// 拼凑条件QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("mobile", mobile);// 查询一个List<User> list = baseMapper.selectList(queryWrapper);if(list.size() == 1) {return list.get(0);}return null;
}  步骤三:修改UserController,添加checkMobile() 方法
/*** 通过手机号查询* @param user* @return*/
@PostMapping("/checkmobile")
public BaseResult checkMobile(@RequestBody User user){//查询用户User findUser = userService.findByMobile( user.getMobile() );//判断if(findUser != null){return BaseResult.error("电话号码已经注册");} else {return BaseResult.ok("电话号码可用");}
}

4.3.3 前端

  • 步骤一:修改api.js,添加 checkMobile() 函数

const request = {test : ()=> {return axios.get('/test')},//检查用户名checkUsername : ( username )=> {return axios.post('/web-service/user/checkusername', { username })},//检查电话号码checkMobile : ( mobile )=> {return axios.post('/web-service/user/checkmobile', { mobile })}
}
  • 步骤二:修改Register.vue,添加 checkMobileFn() 进行手机号检查
  methods: {async checkUsernameFn() {//检查用户名let {data} = await this.$request.checkUsername( this.user.username )this.userMsg.usernameData = data},async checkMobileFn() {//检查电话let {data} = await this.$request.checkMobile( this.user.mobile )this.userMsg.mobileData = data}},
  • 步骤三:编写需要的2个变量
  data() {return {user : {  //表单封装数据username : "",mobile : ""},userMsg : { //错误提示数据usernameData : "",mobileData : ""}}},
  • 步骤四:处理页面
<li><label for="">手机号码:</label><input type="text" class="txt"  name="mobile"  v-model="user.mobile" @blur="checkMobileFn" /><p>请输入手机号码</p><p :class="userMsg.mobileData.code == 1 ? 'success' : 'error'">{{userMsg.mobileData.message}} </p></li>~~~*   完整版~~~vue
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><!-- 登录主体部分start --><div class="login w990 bc mt10 regist"><div class="login_hd"><h2>用户注册</h2><b></b></div><div class="login_bd"><div class="login_form fl"><form action="" method="post"><ul><li><label for="">用户名:</label><input type="text" class="txt" name="username" v-model="user.username" @blur="checkUsernameFn" /><p>3-20位字符,可由中文、字母、数字和下划线组成</p><p :class="userMsg.usernameData.code == 1 ? 'success' : 'error'">{{userMsg.usernameData.message}} </p></li><li><label for="">密码:</label><input type="password" class="txt" name="password" /><p>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号</p></li><li><label for="">确认密码:</label><input type="password" class="txt" name="password" /><p>请再次输入密码</p></li><li><label for="">手机号码:</label><input type="text" class="txt"  name="mobile"  v-model="user.mobile" @blur="checkMobileFn" /><p>请输入手机号码</p><p :class="userMsg.mobileData.code == 1 ? 'success' : 'error'">{{userMsg.mobileData.message}} </p></li><li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode" /><button >发送验证码<span>5秒</span></button></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb" checked="checked" /> 我已阅读并同意《用户注册协议》</li><li><label for="">&nbsp;</label><input type="submit" value="" class="login_btn" /></li></ul></form></div><div class="mobile fl"><h3>手机快速注册</h3><p>中国大陆手机用户,编辑短信 “<strong>XX</strong>”发送到:</p><p><strong>1069099988</strong></p></div></div></div><!-- 登录主体部分end --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户注册',link: [{rel:'stylesheet',href:'style/login.css'}],script: [{ type: 'text/javascript', src: 'js/header.js' },{ type: 'text/javascript', src: 'js/index.js' },]},components : {TopNav,HeaderLogo,Footer},data() {return {user : {  //表单封装数据username : "",mobile : "",password : "",code : ""},userMsg : { //错误提示数据usernameData : "",mobileData : ""}}},methods: {async checkUsernameFn() {//检查用户名let {data} = await this.$request.checkUsername( this.user.username )this.userMsg.usernameData = data},async checkMobileFn() {//检查电话let {data} = await this.$request.checkMobile( this.user.mobile )this.userMsg.mobileData = data}},
}
</script><style></style>

4.4 用户注册:前置技术–Redis

4.5 用户注册:前置技术–阿里大鱼

以往写过短信注册:

https://editor.csdn.net/md/?articleId=121686836

详情就不过赘述

4.6 用户注册:短信验证码

4.6.1 分析

4.6.2 接口

http://localhost:10010/web-service/sms
{"mobile":"13344445555","username": "jack"
}

4.6.3 后端

  • 创建 SmsController类,调用阿里大鱼工具类,发送短信。
package com.czxy.changgou4.controller;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.utils.SmsUtil;
import com.czxy.changgou4.vo.BaseResult;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** Created by   .*/
@RestController
@RequestMapping("/sms")
public class SmsController {@Resourceprivate StringRedisTemplate redisTemplate;@PostMappingpublic BaseResult sendSms(@RequestBody User user){long start = System.currentTimeMillis();try {//发送短信//1 生产验证码String code = RandomStringUtils.randomNumeric(4);System.out.println("验证码:" + code);//2 并存放到reids中 , key: "sms_register" + 手机号 , value:验证码 , 1小时redisTemplate.opsForValue().set( "sms_register" + user.getMobile() , code , 1 , TimeUnit.HOURS);/**///3 发送短信SendSmsResponse smsResponse = SmsUtil.sendSms(user.getMobile(), user.getUsername() , code, "", "");//https://help.aliyun.com/document_detail/55284.html?spm=5176.doc55322.6.557.KvvIJxif("OK".equalsIgnoreCase(smsResponse.getCode())){return BaseResult.ok("发送成功");} else {return BaseResult.error(smsResponse.getMessage());}/*//模拟数据System.out.println("验证码:" + code);return BaseResult.ok("发送成功");*/} catch (Exception e) {long end = System.currentTimeMillis();System.out.println( end - start);return BaseResult.error("发送失败" );}}
}

4.6.4 前端

  • 步骤一:修改apiclient.js,发送短信ajax操作
  //发短信sendSms : ( user )=> {return axios.post('/web-service/sms', user )}
  • 步骤二:修改Register.vue页面,给“发送验证码”绑定点击事件
sendSmsFn
<button  @click.prevent="sendSmsFn" >发送验证码<span>5秒</span></button>

  • 步骤三:修改Register.vue页面,编写sendSmsFn函数,建议采用 ajax…then()…catch 可以处理异常
sendSmsFn () {this.$request.sendSms( this.user ).then(( response )=>{//发送短信的提示信息this.userMsg.smsData = response.data}).catch(( error )=>{//错误提示信息alert( error.message )})}
  • 步骤四:修改Register.vue页面,提供变量smsData
userMsg : { //错误提示数据usernameData : "",mobileData : "",smsData : ""}

  • 步骤五:修改Register.vue页面,显示 smsData提示信息

4.6.5 倒计时

  • 步骤一:提供3个变量,用于控制倒计时

btnDisabled : false, //倒计时控制变量
seconds : 5, //默认倒计时秒数
timer : null, //接收定时器,清除定时器

  • 步骤二:在标签上面控制倒计时的显示

<button :disabled=“btnDisabled” @click.prevent=“sendSmsFn” >
发送验证码{{seconds}}秒


  • 步骤三:发送短信后,开启倒计时控制
sendSmsFn () {this.$request.sendSms( this.user ).then(( response )=>{//发送短信的提示信息this.userMsg.smsData = response.data//按钮不可用this.btnDisabled = true;//倒计时this.timer = setInterval( ()=>{if(this.seconds <= 1){//结束// 重置秒数this.seconds = 5;// 按钮可用this.btnDisabled = false;// 停止定时器clearInterval(this.timer);} else {this.seconds --;}} , 1000);}).catch(( error )=>{//错误提示信息alert( error.message )})}

4.7 用户注册

4.7.1 接口

http://localhost:10010/web-service/user/register
{
“mobile”:“13612345677”,
“password”:“1234”,
“username”:“jack3”,
“code”:“3919”
}

4.7.2 后端

  • 保存前需要再次进行服务端校验
  • 用户名是否注册
  • 手机号是否注册
  • 验证码是否失效
  • 验证码是否错误
  • 密码需要使用 BCrypt进行加密

*步骤一:修改UserService接口,添加register方法

/*** 用户注册* @param user* @return*/
public boolean register(User user) ;

步骤二:完善UserServiceImpl实现类

@Override
public boolean register(User user) {//密码加密String newPassword = BCrypt.hashpw(user.getPassword());user.setPassword(newPassword);//处理数据user.setCreatedAt(new Date());user.setUpdatedAt(user.getCreatedAt());int insert = baseMapper.insert(user);return insert == 1;
}
  • 步骤三:修改UserController,添加register方法
/*** 用户注册* @param user* @return*/
@PostMapping("/register")
public BaseResult  register(@RequestBody User user){//服务端校验User findUser = userService.findByUsername(user.getUsername());if(findUser != null) {return BaseResult.error("用户名已经存在");}findUser = userService.findByMobile(user.getMobile());if(findUser != null) {return BaseResult.error("电话号码已经存在");}//验证码String code = stringRedisTemplate.opsForValue().get("sms_register" + user.getMobile());//删除redis中的验证码stringRedisTemplate.delete("sms_register" + user.getMobile());if(code == null) {return BaseResult.error("验证码失效");}if(!code.equals(user.getCode())) {return BaseResult.error("验证码不正确");}//注册boolean register = userService.register(user);if(register) {return BaseResult.ok("注册成功");}return BaseResult.error("注册失败");
}

4.7.3 日期处理(可选)

  • 编写 DateMetaObjectHandler 用于处理“创建时间”和“修改日期”
package com.czxy.changgou4.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.util.Date;/*** @author zzllforever* @email 2752776684.com*/
@Component
public class DateMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("createdAt", new Date(), metaObject);this.setFieldValByName("updatedAt", new Date(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updatedAt", new Date(), metaObject);}
}
  • 完善User JavaBean,设置填充方式
@TableField(value="created_at",fill = FieldFill.INSERT)
private Date createdAt;@TableField(value="updated_at",fill = FieldFill.INSERT_UPDATE)
private Date updatedAt;

4.7.4 前端

  • 步骤一:修改 api.js ,添加注册函数
  //注册register : ( user )=> {return axios.post('/web-service/user/register', user )}
  • 步骤二:处理表单,验证码input绑定数据,提交按钮绑定事件

          <li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode"  v-model="user.code" /><button  :disabled="btnDisabled" @click.prevent="sendSmsFn" >发送验证码<span v-show="btnDisabled">{{seconds}}秒</span></button><p :class="userMsg.smsData.code == 1 ? 'success' : 'error'">{{userMsg.smsData.message}} </p></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb" checked="checked" /> 我已阅读并同意《用户注册协议》</li><li><label for="">&nbsp;</label><input type="submit" value="" @click.prevent="registerFn" class="login_btn" /></li>
    
  • 步骤三:完善data区域的user数据

user : { //表单封装数据
username : “”, //用户名
mobile : “13699282444”, //手机号
password : “”, //密码
code : “” //验证码
},

  • 步骤四:编写registerFn函数

async registerFn() {
let { data } = await this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …功 this.router.push(’/login’)
} else {
//失败–与发送验证码使用一个位置显示错误信息
this.userMsg.smsData = data
}
}

4.8 用户登录

4.8.1 构建页面:Login.vue

  • 步骤一:创建Login.vue
  • 步骤二:绘制通用模块
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户登录',link: [{rel:'stylesheet',href:'style/login.css'}],script: []},components : {TopNav,HeaderLogo,Footer},}
</script><style></style>
  • 步骤三:绘制登录表单
<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><!-- 登录主体部分start --><div class="login w990 bc mt10"><div class="login_hd"><h2>用户登录</h2><b></b></div><div class="login_bd"><div class="login_form fl"><form action="" method="post"><ul><li><label for="">用户名:</label><input type="text" class="txt" name="username" /></li><li><label for="">密码:</label><input type="password" class="txt" name="password" /><a href="">忘记密码?</a></li><li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode" /><img src="data:images/checkcode1.jpg" alt="" /><span>看不清?<a href="">换一张</a></span></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb"  /> 保存登录信息</li><li><label for="">&nbsp;</label><input type="submit" value="" class="login_btn" /></li></ul></form><div class="coagent mt15"><dl><dt>使用合作网站登录商城:</dt><dd class="qq"><a href=""><span></span>QQ</a></dd><dd class="weibo"><a href=""><span></span>新浪微博</a></dd><dd class="yi"><a href=""><span></span>网易</a></dd><dd class="renren"><a href=""><span></span>人人</a></dd><dd class="qihu"><a href=""><span></span>奇虎360</a></dd><dd class=""><a href=""><span></span>百度</a></dd><dd class="douban"><a href=""><span></span>豆瓣</a></dd></dl></div></div><div class="guide fl"><h3>还不是商城用户</h3><p>现在免费注册成为商城用户,便能立刻享受便宜又放心的购物乐趣,心动不如行动,赶紧加入吧!</p><a href="regist.html" class="reg_btn">免费注册 >></a></div></div></div><!-- 登录主体部分end --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户登录',link: [{rel:'stylesheet',href:'style/login.css'}],script: []},components : {TopNav,HeaderLogo,Footer},}
</script><style></style>

4.8.2 分析

4.8.3 验证码:接口

http://localhost:10010/web-service/verifycode?username=jack

4.8.4 验证码:生成与显示

  • 步骤一:后端生产验证码,并将用户保存Redis
  • 存放redis中验证码key格式:“login” + 用户名
package com.czxy.changgou4.controller;import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;/*** @author zzllforever* @email 2752776684.com*/
@Controller
@RequestMapping("/verifycode")
public class VerifyCodeController {@Resourceprivate StringRedisTemplate stringRedisTemplate;@GetMappingpublic void verifyCode(String username , HttpServletResponse response ) throws IOException {//字体只显示大写,去掉了1,0,i,o几个容易混淆的字符String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";int IMG_WIDTH = 72;int IMG_HEIGTH = 27;Random random = new Random();//创建图片BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGTH, BufferedImage.TYPE_INT_RGB);//画板Graphics g = image.getGraphics();//填充背景g.setColor(Color.WHITE);g.fillRect(1,1,IMG_WIDTH-2,IMG_HEIGTH-2);g.setFont(new Font("楷体", Font.BOLD,25));StringBuilder sb = new StringBuilder();//写字for(int i = 1 ; i <= 4 ; i ++){//随机颜色g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));int len = random.nextInt(VERIFY_CODES.length());String str = VERIFY_CODES.substring(len,len+1);sb.append(str);g.drawString(str, IMG_WIDTH / 6 * i , 22 );}//将验证码存放到redisstringRedisTemplate.opsForValue().set( "login" + username , sb.toString() , 1 , TimeUnit.HOURS);// 生成随机干扰线for (int i = 0; i < 30; i++) {//随机颜色g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));int x = random.nextInt(IMG_WIDTH - 1);int y = random.nextInt(IMG_HEIGTH - 1);int x1 = random.nextInt(12) + 1;int y1 = random.nextInt(6) + 1;g.drawLine(x, y, x - x1, y - y1);}//响应到浏览器ImageIO.write(image,"jpeg", response.getOutputStream());}
}
  • 步骤二:点击“换一张”显示验证码
  • 默认不显示验证码
  • 点击“换一张”获得验证码

<template><div><TopNav></TopNav><div style="clear:both;"></div><HeaderLogo></HeaderLogo><div style="clear:both;"></div><!-- 正文 --><!-- 登录主体部分start --><div class="login w990 bc mt10"><div class="login_hd"><h2>用户登录</h2><b></b></div><div class="login_bd"><div class="login_form fl"><form action="" method="post"><ul><li><label for="">用户名:</label><input type="text" class="txt" name="username" v-model="user.username" /></li><li><label for="">密码:</label><input type="password" class="txt" name="password" v-model="user.password" /><a href="">忘记密码?</a></li><li class="checkcode"><label for="">验证码:</label><input type="text"  name="checkcode" /><!-- <img src="data:images/checkcode1.jpg" alt="" /> --><img :src="imgSrc" alt="" /><span>看不清?<a href="" @click.prevent="changeVerifyCode">换一张</a></span></li><li v-if="errorMsg != ''"><label for="">&nbsp;</label><span style="color: #ff5b5b">{{errorMsg}}</span></li><li><label for="">&nbsp;</label><input type="checkbox" class="chb"  /> 保存登录信息</li><li><label for="">&nbsp;</label><input type="submit" value="" class="login_btn" /></li></ul></form><div class="coagent mt15"><dl><dt>使用合作网站登录商城:</dt><dd class="qq"><a href=""><span></span>QQ</a></dd><dd class="weibo"><a href=""><span></span>新浪微博</a></dd><dd class="yi"><a href=""><span></span>网易</a></dd><dd class="renren"><a href=""><span></span>人人</a></dd><dd class="qihu"><a href=""><span></span>奇虎360</a></dd><dd class=""><a href=""><span></span>百度</a></dd><dd class="douban"><a href=""><span></span>豆瓣</a></dd></dl></div></div><div class="guide fl"><h3>还不是商城用户</h3><p>现在免费注册成为商城用户,便能立刻享受便宜又放心的购物乐趣,心动不如行动,赶紧加入吧!</p><a href="regist.html" class="reg_btn">免费注册 >></a></div></div></div><!-- 登录主体部分end --><div style="clear:both;"></div><Footer></Footer></div>
</template><script>
import TopNav from '../components/TopNav'
import HeaderLogo from '../components/HeaderLogo'
import Footer from '../components/Footer'
export default {head: {title: '用户登录',link: [{rel:'stylesheet',href:'style/login.css'}],script: []},components : {TopNav,HeaderLogo,Footer},data() {return {imgSrc:'',errorMsg: '',user: {}}},methods: {changeVerifyCode() {if( this.user.username ) {this.imgSrc = `http://localhost:10010/web-service/verifycode?t=${new Date().getTime()}&username=${this.user.username }`} else {this.errorMsg = '用户名不能为空'}}},watch: {'user' : {handler(v) {if(v) {//如果user数据发生改变,修改提示信息this.errorMsg = ''}},deep: true}},}
</script><style></style>

4.8.5 通过用户名查询:接口

http://localhost:10010/web-service/user/findByUsername {
“username”:“jack” }

电商项目:畅购商城4.0相关推荐

  1. 尚硅谷2020微服务分布式电商项目《谷粒商城》学习笔记

    尚硅谷2020微服务分布式电商项目<谷粒商城> 项目简介 资料 百度云 链接:https://pan.baidu.com/s/1eGCTi6pLtKbDCwBs-zCOzQ 提取码:1pm ...

  2. 畅购商城4.0 微信支付

    畅购商城4.0 1.微信支付 1.1流程分析 1.2微信支付概述 1.2.1账号申请 步骤一:注册公众号,根据自身主体类型注册对应的公众号 只能申请服务号,订阅号没有办法申请支付 https:// ...

  3. 前端电商项目实战,如何从 0 开始创造一个【考拉海购官网】?( 共6节教程 )

    文章目录 声明 一,关于页面还原度效果比较 二,第一组演示图是 考拉海购官网的 三,第二组演示图是 本次教程从0开发的 四,教程目录(共6节) 五,全部代码下载地址 新手提示 (1)如何从github ...

  4. 尚硅谷2020微服务分布式电商项目《谷粒商城》-单点登录(jwt)

    学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 用户管理提供数据接口 1.1. 数据验证功能 根据接口文档知: 请求方式:GET 请求路径:check ...

  5. 尚硅谷2020微服务分布式电商项目《谷粒商城》-支付、秒杀

    学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 支付 订单搞定之后就是支付了,首先搭建支付工程. 1.1. 搭建环境 pom.xml <?xml ...

  6. 尚硅谷2020微服务分布式电商项目《谷粒商城》-商品搜索

    关注公众号:java星星 获取全套课件资料 1. 导入商品数据 1.1. 搭建搜索工程 pom.xml内容如下: <?xml version="1.0" encoding=& ...

  7. 微服务分布式电商项目《谷粒商城》学习笔记

    文章目录 一.基本架构图 二.配置 三.项目搭建 四.数据库 1.开启虚拟机,在windows下通过navicat连接上 2.人人开源:https://gitee.com/renrenio 五.微服务 ...

  8. JavaWeb实战项目之乐购商城V1.0(一)-------环境搭建

    一.操作系统 Linux6.8  64位 关于sudo权限问题,参照:http://blog.csdn.net/dream_angel_z/article/details/45841109 二.配置阿 ...

  9. WEB小厂电商项目测试技术指南1.0

    中高级测试工程师技术及要求 需求分析 要求: 参与需求评审会前要先看几遍需求文档. 分析需求的可行性,不可行的点可以在会议中提出来沟通. 需求的完整性,有不足的地方提出来让产品优化或给出建议. 需求测 ...

  10. SpringBoot+SpringCloud+Mybatis+Vue 电商项目实战,附视频+源码+文档,包含所有主流技术栈。...

    大家好,我是树哥. 今天给大家分享一个电商项目--- 畅购商城.项目采用前后端分离的技术架构. 采用SpringBoot+SpringCloud+Mybatis+Vue为主要技术栈,包括了大型商城的主 ...

最新文章

  1. C++程序设计之函数对象
  2. 自学Springboot(一)
  3. php定时红包,PHP随机红包和等额红包的简单实现
  4. Java命令行界面(第10部分):picocli
  5. leetcode337. 打家劫舍 III(dfs)
  6. Activity 启动模式
  7. FFMPEG结构体分析:AVFrame
  8. 工行基于MySQL构建分布式架构的转型之路
  9. 谈谈R中的乱码(三)
  10. 创业者都认为经营一家新公司最主要的目标是融资
  11. day-15 磁盘挂载 磁盘格式化
  12. android ukey,4uKey for Android
  13. com/lsass.exe smss.exe(磁碟机病毒) 感染方式之我分析 -- 2008第一博
  14. Python pandas,pandas.series,series的主要方法
  15. 设计原则Python
  16. 腾讯面试题, 2020年,让我们愉快的赛一次马!
  17. IR-CUT选择须知
  18. 基于flask构建微服基本demo
  19. Maximum Likelihood (MLE) Maximum a posteriori (MAP)的分別
  20. 文件传输协议:FTP和TFTP

热门文章

  1. springboot酒店客房预定管理系统
  2. JAVA 面试 知识点整理
  3. Python数组索引
  4. 一行代码统计文本中指定字符串出现的次数
  5. 为什么CU和DU要分离?
  6. u-boot-2010.09-for-tiny6410-v1.0支持sd卡SDHC卡启动
  7. arm-linux-gcc踩坑1
  8. android后台前台切换,Android 把后台应用切换到前台
  9. PLC温室大棚自动控制系统
  10. qq、微信能打开,网页打不开的解决办法。