基于SpringBoot构建电商秒杀项目代码实例

网友投稿 309 2022-12-06


基于SpringBoot构建电商秒杀项目代码实例

一、项目功能概述

电商秒杀需要完成的3个功能:

1.展示一个商品列表页面,我们可以从中看到可秒杀的商品列表

2.点击进入商品详情页,获取该商品的详细信息

3.秒杀时间开始后,点击进入下单确认页面,并支付成功

二、基于SpringBoot进行项目环境搭建

步骤1:创建一个maven工程,使用quickStart骨架。

步骤2:在pom.xml导入SpringBoot相关依赖。

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.example

Spike

1.0-SNAPSHOT

Spike

http://example.com

org.springframework.boot

spring-boot-starter-parent

2.0.5.RELEASE

UTF-8

1.8 1.8

org.springframework.boot

spring-boot-starter-web

junit

junit

4.11

test

maven-clean-plugin

3.1.0

maven-resources-plugin

3.0.2

maven-compiler-plugin

3.8.0

maven-surefire-plugin

2.22.1

maven-jar-plugin

3.0.2

maven-install-plugin

2.5.2

maven-deploy-plugin

2.8.2

maven-site-plugin

3.7.1

maven-project-info-reports-plugin

3.0.0

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.example

Spike

1.0-SNAPSHOT

Spike

http://example.com

org.springframework.boot

spring-boot-starter-parent

2.0.5.RELEASE

UTF-8

1.8 1.8

org.springframework.boot

spring-boot-starter-web

junit

junit

4.11

test

maven-clean-plugin

3.1.0

maven-resources-plugin

3.0.2

maven-compiler-plugin

3.8.0

maven-surefire-plugin

2.22.1

maven-jar-plugin

3.0.2

maven-install-plugin

2.5.2

maven-deploy-plugin

2.8.2

maven-site-plugin

3.7.1

maven-project-info-reports-plugin

3.0.0

步骤3:在main/java/app中,我们对SpringBoot和SpringMVC进行简单的配置工作。掌握这几个注解的作用。

package org.example;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

//SpringBoot会帮我们启动tomcat,并加载默认配置

@EnableAutoConfiguration

//SpringMVC相关配置

@RestController

public class App {

@RequestMapping("/")

public String home(){

//网页中输出

return "Hello World!";

}

public static void main( String[] args ){

//控制台输出

System.out.println( "Hello World!" );

SpringApplication.run(App.class,args);

}

}

运行结果:

用浏览器打开http://localhost:8080/,我们可以看到页面上输出:Hello World!

同时,控制台也输出了Hello World!,以及一些Spring相关的信息。

SpringBoot小技巧:可以在resource目录下创建一个application.propeties配置文件,在其中写:server.port = 端口号来设置端口号。

步骤4:接入mybatis,首先在pom.xml添加需要的依赖(mysql,druid连接池,mybatis)

写一个plugin标签,引入对应的mybatis自动生成文件的插件 {

添加对应的依赖:mybatis generator的core(第一次使用要单独在前面导入依赖,不可直接放在plugin中),mysql数据库的解析

写一个excution标签:设置允许移动生成的文件,允许自动覆盖文件(实际工作中不可以)

写一个configuration标签:指定mybatis generator 配置文件的路径 }

1

2

3

4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

5 4.0.0

6

7 org.example

8 Spike

9 1.0-SNAPSHOT

10

11 Spike

12

13 http://example.com

14

15

16 org.springframework.boot

17 spring-boot-starter-parent

18 2.0.5.RELEASE

19

20

21

22 UTF-8

23 1.8

24 1.8

25

26

27

28

29 org.springframework.boot

30 spring-boot-starter-web

31

32

33 mysql

34 mysql-connector-java

35 5.1.6

36

37

38 com.alibaba

39 druid

40 1.1.3

41

42

43 org.mybatis.spring.boot

44 mybatis-spring-boot-starter

45 1.3.1

46

47

48 junit

49 junit

50 4.11

51 test

52

53

54 org.mybatis.generator

55 mybatis-generator-core

56 1.3.5

57

58

59

60

61

62

63

64

65 maven-clean-plugin

66 3.1.0

67

68

69

70 maven-resources-plugin

71 3.0.2

72

73

74 maven-compiler-plugin

75 3.8.0

76

77

78 maven-surefire-plugin

79 2.22.1

80

81

82 maven-jar-plugin

83 3.0.2

84

85

86 maven-install-plugin

87 2.5.2

88

89

90 maven-deploy-plugin

91 2.8.2

92

93

94

95

96 maven-site-plugin

97 3.7.1

98

99

100 maven-project-info-reports-plugin

101 3.0.0

102

103

104

105 org.mybatis.generator

106 mybatis-generator-maven-plugin

107 1.3.5

108

109

110 org.mybatis.generator

111 mybatis-generator-core

112 1.3.5

113

114

115 mysql

116 mysql-connector-java

117 5.1.6

118

119

120

121

122 mybatis generator

123 package

124

125 generate

126

127

128

129

130

131 true

132

133 true

134

135

136 src/main/resource/mybatis-generator.xml

137

138

139

140

141

142

143

144

4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

5 4.0.0

6

7 org.example

8 Spike

9 1.0-SNAPSHOT

10

11 Spike

12

13 http://example.com

14

15

16 org.springframework.boot

17 spring-boot-starter-parent

18 2.0.5.RELEASE

19

20

21

22 UTF-8

23 1.8

24 1.8

25

26

27

28

29 org.springframework.boot

30 spring-boot-starter-web

31

32

33 mysql

34 mysql-connector-java

35 5.1.6

36

37

38 com.alibaba

39 druid

40 1.1.3

41

42

43 org.mybatis.spring.boot

44 mybatis-spring-boot-starter

45 1.3.1

46

47

48 junit

49 junit

50 4.11

51 test

52

53

54 org.mybatis.generator

55 mybatis-generator-core

56 1.3.5

57

58

59

60

61

62

63

64

65 maven-clean-plugin

66 3.1.0

67

68

69

70 maven-resources-plugin

71 3.0.2

72

73

74 maven-compiler-plugin

75 3.8.0

76

77

78 maven-surefire-plugin

79 2.22.1

80

81

82 maven-jar-plugin

83 3.0.2

84

85

86 maven-install-plugin

87 2.5.2

88

89

90 maven-deploy-plugin

91 2.8.2

92

93

94

95

96 maven-site-plugin

97 3.7.1

98

99

100 maven-project-info-reports-plugin

101 3.0.0

102

103

104

105 org.mybatis.generator

106 mybatis-generator-maven-plugin

107 1.3.5

108

109

110 org.mybatis.generator

111 mybatis-generator-core

112 1.3.5

113

114

115 mysql

116 mysql-connector-java

117 5.1.6

118

119

120

121

122 mybatis generator

123 package

124

125 generate

126

127

128

129

130

131 true

132

133 true

134

135

136 src/main/resource/mybatis-generator.xml

137

138

139

140

141

142

143

144

步骤5:创建mysql底层的数据库与相关表格

1.创建数据库spike

2.创建一个user_info表格

3.创建一个user_password表格,并设置user_id为外键关联user_info的id

步骤6:在步骤4中,我们最后指定了mybatis generator 配置文件的路径,于是我们在指定路径(resource目录下)创建一个mybatis generator.xml,并进行如下配置:

PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

enableUpdateByExample="false" enableDeleteByExample="false"

enableSelectByExample="false" selectByExampleQueryId="false"

>

enableUpdateByExample="false" enableDeleteByExample="false"

enableSelectByExample="false" selectByExampleQueryId="false"

>

步骤7:根据步骤6中指定的位置,我们在org.example目录下新建一个dataobject的包,一个dao包。并测试是否能够成功生成相应的文件:

run——edit configurations——+maven——command line:mybatis-generator:generate——apply

然后我们运行这个新建的命令,可以看到resources/mapping下多了两个文件:

dataobject包与dao包下生成了如下文件:

手动删除两个Example文件。

步骤8:为了接入mybatis对应mysql的数据源,我们继续编写application.properties文件

server.port = 8090

mybatis.mapperLocations = classpath:mapping/*.xml

spring.datasource.name = Spike

spring.datasource.url = jdbc:mysql://127.0.0.1:3306/Spike

spring.datasource.username = root

spring.datasource.password = 0322

#使用druid数据源

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource

spring.datasource.driverClassName = com.mysql.jdbc.Driver

步骤9:回到app.java

将@EnableAutoConfiguration注解改为@SpringBootApplication(scanBasePackages = "org.example"),作用是将app交给spring托管,并且指定为主启动类。

添加注解@MapperScan("org.example.dao"),把dao存放的地方设置在对应注解下面。

最后,写一个方法来测试我们的搭建工作是否完成,(事先在表格中添加一条数据)

package org.example;

import org.example.dao.UserDoMapper;

import org.example.dataobject.UserDo;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

//SpringBoot会帮我们启动tomcat,并加载默认配置

@SpringBootApplication(scanBasePackages = {"org.example"})

//SpringMVC相关配置

@RestController

@MapperScan("org.example.dao")

public class App {

@Autowired

private UserDoMapper userDoMapper;

@RequestMapping("/")

public String home(){

UserDo userDo = userDoMapper.selectByPrimaryKey(1);

if(userDo == null){

return "用户对象不存在";

}else{

return userDo.getName();

}

}

public static void main( String[] args ){

//控制台输出

System.out.println( "Hello World!" );

SpringApplication.run(App.class,args);

}

}

app.java

打开http://localhost:8090/,我们可以看到页面上显示了我们添加的数据中name字段的内容。

三、用户模块开发

1.使用SpingMVC模式开发用户信息

步骤1:补全框架结构:

步骤2:service层的编写:

UserService接口:

package org.example.service;

import org.example.service.model.UserModel;

public interface UserService {

UserModel getUserById(Integer id);

}

UserService实现类:

@Service

public class UserServiceImpl implements UserService {

@Autowired

private UserDoMapper userDoMapper;

@Autowired

private UserPasswordDOMapper userPasswordDOMapper;

@Override

public UserModel getUserById(Integer id) {

UserDo userDo = userDoMapper.selectByPrimaryKey(id);

if(userDo == null){

return null;

}

//通过用户id获取对应的用户加密密码信息

UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDo.getId());

return convertFromDataObject(userDo,userPasswordDO);

}

public UserModel convertFromDataObject(UserDo userDo, UserPasswordDO userPasswordDO) {

if(userDo == null){

return null;

}

UserModel userModel = new UserModel();

BeanUtils.copyProperties(userDo,userModel);

if(userPasswordDO != null){

userModel.setEncriptPassword(userPasswordDO.getEncriptPassword());

}

return userModel;

}

}

UserModel类:存放数据库的所有对应字段与getters&setters,用于service层与数据库数据的解耦,使service层无法直接接触数据库

1 package org.example.service.model;

2

3 public class UserModel {

4 private Integer id;

5 private String name;

6 private Byte gender;

7 private Integer age;

8 private String telephone;

9 private String registerMode;

10 private String thirdPartyId;

11 private String encriptPassword;

12

13 public Integer getId() {

14 return id;

15 }

16

17 public void setId(Integer id) {

18 this.id = id;

19 }

20

21 public String getName() {

22 return name;

23 }

24

25 public void setName(String name) {

26 this.name = name;

27 }

28

29 public Byte getGender() {

30 return gender;

31 }

32

33 public void setGender(Byte gender) {

34 this.gender = gender;

35 }

36

37 public Integer getAge() {

38 return age;

39 }

40

41 public void setAge(Integer age) {

42 this.age = age;

43 }

44

45 public String getTelephone() {

46 return telephone;

47 }

48

49 public void setTelephone(String telephone) {

50 this.telephone = telephone;

51 }

52

53 public String getRegisterMode() {

54 return registerMode;

55 }

56

57 public void setRegisterMode(String registerMode) {

58 this.registerMode = registerMode;

59 }

60

61 public String getThirdPartyId() {

62 return thirdPartyId;

63 }

64

65 public void setThirdPartyId(String thirdPartyId) {

66 this.thirdPartyId = thirdPartyId;

67 }

68

69 public String getEncriptPassword() {

70 return encriptPassword;

71 }

72

73 public void setEncriptPassword(String encriptPassword) {

74 this.encriptPassword = encriptPassword;

75 }

76 }

步骤3:修改UserPasswordDOMapper.xml,添加一个selectByUserId操作的配置

select

from user_password

where user_id = #{userId,jdbcType=INTEGER}

同步修改UserPasswordDOMapper.java,添加一行代码:

UserPasswordDO selectByUserId(Integer userId);

步骤4:编写Controller包中的UserController.java

@Controller("user")

@RequestMapping("/user")

public class UserController {

@Autowired

private UserService userService;

@RequestMapping("/get")

@ResponseBody

public UserModel getUser(@RequestParam(name="id") Integer id) {

//调用service服务获取对应id的用户对象并返回给前端

UserModel userModel = userService.getUserById(id);

return userModel;

}

}

运行后,访问http://localhost:8090/user/get?id=1(需要事先添加好一条完整的数据),可以看到页面上输出了这条数据的完整信息。

步骤5:发现问题:在UserController中,我们把userModel模型直接返回给前端,导致密码直接输出在页面中,这是非常不专业的。

因此,我们在controller层(包)中需要新建一个模型对象。在controller层中新建一个viewobject包,并在其中写一个viewobject类,里面只写需要展示在前端的字段与getters&setters。

1 package org.example.controller.viewobject;

2

3 public class UserVO {

4 //只写前端用户所需要的信息

5 private Integer id;

6 private String name;

7 private Byte gender;

8 private Integer age;

9 private String telephone;

10

11 public Integer getId() {

12 return id;

13 }

14

15 public void setId(Integer id) {

16 this.id = id;

17 }

18

19 public String getName() {

20 return name;

21 }

22

23 public void setName(String name) {

24 this.name = name;

25 }

26

27 public Byte getGender() {

28 return gender;

29 }

30

31 public void setGender(Byte gender) {

32 this.gender = gender;

33 }

34

35 public Integer getAge() {

36 return age;

37 }

38

39 public void setAge(Integer age) {

40 this.age = age;

41 }

42

43 public String getTelephone() {

44 return telephone;

45 }

46

47 public void setTelephone(String telephone) {

48 this.telephone = telephone;

49 }

50 }

同时,我们修改UserController类,将UserModel转化为viewobject后,再返回给前端。

@Controller("user")

@RequestMapping("/user")

public class UserController {

@Autowired

private UserService userService;

@RequestMapping("/get")

@ResponseBody

public UserVO getUser(@RequestParam(name="id") Integer id) {

//调用service服务获取对应id的用户对象并返回给前端

UserModel userModel = userService.getUserById(id);

//将核心领域模型对象转化为可供UI使用的viewobject

return convertFromModel(userModel);

}

private UserVO convertFromModel(UserModel userModel){

if(userModel == null){

return null;

}

UserVO userVO = new UserVO();

BeanUtils.copyProperties(userModel,userVO);

return userVO;

}

}

这一步中,我们做了一个完整的从数据库中读取数据,展示在前端页面上的操作。

controller层——>service层——>dao层

dataobject层负责数据存储到service的传输,并且在用户的service的服务中组装了对应的核心领域模型。

controller层做了到用户viewobject之间的传递,保证密码等信息不会输出到前端。

2.定义通用的返回对象

步骤1:自主管理前端页面的返回——返回正确信息

org.example包下创建一个response包,在其中创建一个CommonReturnType.java文件。

在该文件中,设置两个属性:status,data,并生成对应的getters&setters。然后写两个构造方法,包含了两个属性的设置。

package org.example.response;

public class CommonReturnType {

//表名对应请求的返回处理结果,success/fail

private String status;

//若status返回success,则data内返回前端需要的json数据

//若status返回success,则data内使用通用的错误码格式

private Object data;

//定义一个通用的创建方法

public static CommonReturnType create(Object result){

return CommonReturnType.create(result,"success");

}

public static CommonReturnType create(Object result,String status){

CommonReturnType type = new CommonReturnType();

type.setStatus(status);

type.setData(result);

return type;

}

public String getStatus() {

return status;

}

public void setStatus(String status) {

this.status = status;

}

public Object getData() {

return data;

}

public void setData(Object data) {

this.data = data;

}

}

修改我们的UserController.java,将返回值改为CommonReturnType,由CommonReturnType调用create方法来引用UserVO中的信息。以下代码为需要修改的部分:

public CommonReturnType getUser(@RequestParam(name="id") Integer id) {

//调用service服务获取对应id的用户对象并返回给前端

UserModel userModel = userService.getUserById(id);

//将核心领域模型对象转化为可供UI使用的viewobject

UserVO userVO = convertFromModel(userModel);

//返回通用对象

return CommonReturnType.create(userVO);

}

运行后,我们仍然访问http://localhost:8090/user/get?id=1,可以看到页面上输出了:

步骤2:自主管理前端页面的返回——返回错误信息

org.example包下创建一个error包,在其中创建一个CommonError接口,写3个方法:获取错误码,获取错误信息,设置错误信息

public interface CommonError {

public int getErrCode();

public String getErrMsg();

public CommonError setErrMsg(String errMsg);

}

error包下写一个枚举类型的EmBusinessError,实现CommonError接口。

package org.example.error;

public enum EmBusinessError implements CommonError{

//通用错误类型10001

PARAMETER_VALIDATION_ERROR(10001,"参数不合法"),

//未知错误10002

UNKNOWN_ERROR(10002,"未知错误"),

//20000开头相关为用户信息相关错误定义

USER_NOT_EXIST(20001,"用户不存在"),

;

private EmBusinessError(int errCode,String errMsg){

this.errCode = errCode;

this.errMsg = errMsg;

}

private int errCode;

private String errMsg;

@Override

public int getErrCode() {

return this.errCode;

}

@Override

public String getErrMsg() {

return this.errMsg;

}

@Override

public CommonError setErrMsg(String errMsg) {

this.errMsg = errMsg;

return this;

}

}

error包下写一个BusinessException,实现CommonError接口,并继承Exception类。

public class BusinessException extends Exception implements CommonError{

private CommonError commonError;

//直接接收EmBusinessError的传参用于构造业务异常

public BusinessException(CommonError commonError) {

super();

this.commonError = commonError;

}

public BusinessException(CommonError commonError,String errMsg) {

super();

this.commonError = commonError;

this.commonError.setErrMsg(errMsg);

}

@Override

public int getErrCode() {

return this.commonError.getErrCode();

}

@Override

public String getErrMsg() {

return this.commonError.getErrMsg();

}

@Override

public CommonError setErrMsg(String errMsg) {

this.commonError.setErrMsg(errMsg);

return this;

}

}

UserController中添加如下代码:

//若获取的对应用户信息不存在

if(userModel==null){

throw new BusinessException(EmBusinessError.USER_NOT_EXIST);

}

步骤3:异常处理

在controller目录下单独写一个BaseController类,定义exceptionhandler解决未被controller层吸收的exception。

import java.util.Map;

public class BaseController {

//定义exceptionhandler解决未被controller层吸收的exception

@ExceptionHandler(Exception.class)

@ResponseStatus(HttpStatus.OK)

@ResponseBody

public Object handlerException(HttpServletRequest request, Exception ex){

Map responseData = new HashMap<>();

if(ex instanceof BusinessException){

BusinessException businessException = (BusinessException)ex;

responseData.put("errCode",businessException.getErrCode());

responseData.put("errMsg",businessException.getErrMsg());

}else{

responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());

responseData.put("errMsg",EmBusinessError.UNKNOWN_ERROR.getErrMsg());

}

return CommonReturnType.create(responseData,"fail");

}

}

然后,UserController类需要继承BaseController类。

运行后,我们访问http://localhost:8090/user/get?id=2,(id=2的数据是不存在的),可以看到页面为:

为了程序的健壮性,我们在BaseController中添加了一个unknown error。我们可以手动地来测试一下这段代码是否起了作用:

修改UserController部分代码如下:

if(userModel==null){

userModel.setEncriptPassword("123");

//throw new BusinessException(EmBusinessError.USER_NOT_EXIST);

}

运行后,我们再次访问http://localhost:8090/user/get?id=2,可以看到页面为:


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:IDEA 中使用 ECJ 编译出现 java.lang.IllegalArgumentException的错误问题
下一篇:Java项目实现寻找迷宫出路
相关文章

 发表评论

暂时没有评论,来抢沙发吧~