基于SpringBoot構(gòu)建電商秒殺項(xiàng)目代碼實(shí)例
一、項(xiàng)目功能概述
電商秒殺需要完成的3個(gè)功能:
1.展示一個(gè)商品列表頁(yè)面,我們可以從中看到可秒殺的商品列表
2.點(diǎn)擊進(jìn)入商品詳情頁(yè),獲取該商品的詳細(xì)信息
3.秒殺時(shí)間開(kāi)始后,點(diǎn)擊進(jìn)入下單確認(rèn)頁(yè)面,并支付成功
二、基于SpringBoot進(jìn)行項(xiàng)目環(huán)境搭建
步驟1:創(chuàng)建一個(gè)maven工程,使用quickStart骨架。
步驟2:在pom.xml導(dǎo)入SpringBoot相關(guān)依賴。
<?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>org.example</groupId>
<artifactId>Spike</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Spike</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
步驟3:在main/java/app中,我們對(duì)SpringBoot和SpringMVC進(jìn)行簡(jiǎn)單的配置工作。掌握這幾個(gè)注解的作用。
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會(huì)幫我們啟動(dòng)tomcat,并加載默認(rèn)配置
@EnableAutoConfiguration
//SpringMVC相關(guān)配置
@RestController
public class App {
@RequestMapping("/")
public String home(){
//網(wǎng)頁(yè)中輸出
return "Hello World!";
}
public static void main( String[] args ){
//控制臺(tái)輸出
System.out.println( "Hello World!" );
SpringApplication.run(App.class,args);
}
}
運(yùn)行結(jié)果:
用瀏覽器打開(kāi)http://localhost:8080/,我們可以看到頁(yè)面上輸出:Hello World!
同時(shí),控制臺(tái)也輸出了Hello World!,以及一些Spring相關(guān)的信息。
SpringBoot小技巧:可以在resource目錄下創(chuàng)建一個(gè)application.propeties配置文件,在其中寫(xiě):server.port = 端口號(hào)來(lái)設(shè)置端口號(hào)。
步驟4:接入mybatis,首先在pom.xml添加需要的依賴(mysql,druid連接池,mybatis)
寫(xiě)一個(gè)plugin標(biāo)簽,引入對(duì)應(yīng)的mybatis自動(dòng)生成文件的插件 {
添加對(duì)應(yīng)的依賴:mybatis generator的core(第一次使用要單獨(dú)在前面導(dǎo)入依賴,不可直接放在plugin中),mysql數(shù)據(jù)庫(kù)的解析
寫(xiě)一個(gè)excution標(biāo)簽:設(shè)置允許移動(dòng)生成的文件,允許自動(dòng)覆蓋文件(實(shí)際工作中不可以)
寫(xiě)一個(gè)configuration標(biāo)簽:指定mybatis generator 配置文件的路徑 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>org.example</groupId> 8 <artifactId>Spike</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <name>Spike</name> 12 <!-- FIXME change it to the project's website --> 13 <url>http://www.example.com</url> 14 15 <parent> 16 <groupId>org.springframework.boot</groupId> 17 <artifactId>spring-boot-starter-parent</artifactId> 18 <version>2.0.5.RELEASE</version> 19 </parent> 20 21 <properties> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 23 <maven.compiler.source>1.8</maven.compiler.source> 24 <maven.compiler.target>1.8</maven.compiler.target> 25 </properties> 26 27 <dependencies> 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-web</artifactId> 31 </dependency> 32 <dependency> 33 <groupId>mysql</groupId> 34 <artifactId>mysql-connector-java</artifactId> 35 <version>5.1.6</version> 36 </dependency> 37 <dependency> 38 <groupId>com.alibaba</groupId> 39 <artifactId>druid</artifactId> 40 <version>1.1.3</version> 41 </dependency> 42 <dependency> 43 <groupId>org.mybatis.spring.boot</groupId> 44 <artifactId>mybatis-spring-boot-starter</artifactId> 45 <version>1.3.1</version> 46 </dependency> 47 <dependency> 48 <groupId>junit</groupId> 49 <artifactId>junit</artifactId> 50 <version>4.11</version> 51 <scope>test</scope> 52 </dependency> 53 <dependency> 54 <groupId>org.mybatis.generator</groupId> 55 <artifactId>mybatis-generator-core</artifactId> 56 <version>1.3.5</version> 57 </dependency> 58 </dependencies> 59 60 <build> 61 <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> 62 <plugins> 63 <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> 64 <plugin> 65 <artifactId>maven-clean-plugin</artifactId> 66 <version>3.1.0</version> 67 </plugin> 68 <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> 69 <plugin> 70 <artifactId>maven-resources-plugin</artifactId> 71 <version>3.0.2</version> 72 </plugin> 73 <plugin> 74 <artifactId>maven-compiler-plugin</artifactId> 75 <version>3.8.0</version> 76 </plugin> 77 <plugin> 78 <artifactId>maven-surefire-plugin</artifactId> 79 <version>2.22.1</version> 80 </plugin> 81 <plugin> 82 <artifactId>maven-jar-plugin</artifactId> 83 <version>3.0.2</version> 84 </plugin> 85 <plugin> 86 <artifactId>maven-install-plugin</artifactId> 87 <version>2.5.2</version> 88 </plugin> 89 <plugin> 90 <artifactId>maven-deploy-plugin</artifactId> 91 <version>2.8.2</version> 92 </plugin> 93 94 <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> 95 <plugin> 96 <artifactId>maven-site-plugin</artifactId> 97 <version>3.7.1</version> 98 </plugin> 99 <plugin> 100 <artifactId>maven-project-info-reports-plugin</artifactId> 101 <version>3.0.0</version> 102 </plugin> 103 104 <plugin> 105 <groupId>org.mybatis.generator</groupId> 106 <artifactId>mybatis-generator-maven-plugin</artifactId> 107 <version>1.3.5</version> 108 <dependencies> 109 <dependency> 110 <groupId>org.mybatis.generator</groupId> 111 <artifactId>mybatis-generator-core</artifactId> 112 <version>1.3.5</version> 113 </dependency> 114 <dependency> 115 <groupId>mysql</groupId> 116 <artifactId>mysql-connector-java</artifactId> 117 <version>5.1.6</version> 118 </dependency> 119 </dependencies> 120 <executions> 121 <execution> 122 <id>mybatis generator</id> 123 <phase>package</phase> 124 <goals> 125 <goal>generate</goal> 126 </goals> 127 </execution> 128 </executions> 129 <configuration> 130 <!--允許移動(dòng)生成的文件--> 131 <verbose>true</verbose> 132 <!--允許自動(dòng)覆蓋文件--> 133 <overwrite>true</overwrite> 134 <!--mybatis generator 配置文件的路徑--> 135 <configurationFile> 136 src/main/resource/mybatis-generator.xml 137 </configurationFile> 138 </configuration> 139 </plugin> 140 141 </plugins> 142 </pluginManagement> 143 </build> 144 </project>
步驟5:創(chuàng)建mysql底層的數(shù)據(jù)庫(kù)與相關(guān)表格
1.創(chuàng)建數(shù)據(jù)庫(kù)spike
2.創(chuàng)建一個(gè)user_info表格

3.創(chuàng)建一個(gè)user_password表格,并設(shè)置user_id為外鍵關(guān)聯(lián)user_info的id

步驟6:在步驟4中,我們最后指定了mybatis generator 配置文件的路徑,于是我們?cè)谥付窂剑╮esource目錄下)創(chuàng)建一個(gè)mybatis generator.xml,并進(jìn)行如下配置:
<?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="mysql" targetRuntime="MyBatis3" >
<!--數(shù)據(jù)庫(kù)連接地址賬號(hào)密碼-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/spike" userId="root" password="0322">
</jdbcConnection>
<!--生成Data Object類存放位置-->
<javaModelGenerator targetPackage="org.example.dataobject" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--生成映射文件存放位置-->
<sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成dao類存放位置-->
<javaClientGenerator targetPackage="org.example.dao" type="XMLMAPPER" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--生成對(duì)應(yīng)表及類名-->
<table tableName="user_info" domainObjectName="UserDo" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false"
></table>
<table tableName="user_password" domainObjectName="UserPasswordDO" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false"
></table>
</context>
</generatorConfiguration>
步驟7:根據(jù)步驟6中指定的位置,我們?cè)趏rg.example目錄下新建一個(gè)dataobject的包,一個(gè)dao包。并測(cè)試是否能夠成功生成相應(yīng)的文件:
run——edit configurations——+maven——command line:mybatis-generator:generate——apply
然后我們運(yùn)行這個(gè)新建的命令,可以看到resources/mapping下多了兩個(gè)文件:

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

手動(dòng)刪除兩個(gè)Example文件。
步驟8:為了接入mybatis對(duì)應(yīng)mysql的數(shù)據(jù)源,我們繼續(xù)編寫(xiě)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數(shù)據(jù)源 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托管,并且指定為主啟動(dòng)類。
添加注解@MapperScan("org.example.dao"),把dao存放的地方設(shè)置在對(duì)應(yīng)注解下面。
最后,寫(xiě)一個(gè)方法來(lái)測(cè)試我們的搭建工作是否完成,(事先在表格中添加一條數(shù)據(jù))
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會(huì)幫我們啟動(dòng)tomcat,并加載默認(rèn)配置
@SpringBootApplication(scanBasePackages = {"org.example"})
//SpringMVC相關(guān)配置
@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 "用戶對(duì)象不存在";
}else{
return userDo.getName();
}
}
public static void main( String[] args ){
//控制臺(tái)輸出
System.out.println( "Hello World!" );
SpringApplication.run(App.class,args);
}
}
app.java
打開(kāi)http://localhost:8090/,我們可以看到頁(yè)面上顯示了我們添加的數(shù)據(jù)中name字段的內(nèi)容。
三、用戶模塊開(kāi)發(fā)
1.使用SpingMVC模式開(kāi)發(fā)用戶信息
步驟1:補(bǔ)全框架結(jié)構(gòu):

步驟2:service層的編寫(xiě):
UserService接口:
package org.example.service;
import org.example.service.model.UserModel;
public interface UserService {
UserModel getUserById(Integer id);
}
UserService實(shí)現(xiàn)類:
@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;
}
//通過(guò)用戶id獲取對(duì)應(yīng)的用戶加密密碼信息
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類:存放數(shù)據(jù)庫(kù)的所有對(duì)應(yīng)字段與getters&setters,用于service層與數(shù)據(jù)庫(kù)數(shù)據(jù)的解耦,使service層無(wú)法直接接觸數(shù)據(jù)庫(kù)
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,添加一個(gè)selectByUserId操作的配置
<select id="selectByUserId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user_password
where user_id = #{userId,jdbcType=INTEGER}
</select>
同步修改UserPasswordDOMapper.java,添加一行代碼:
UserPasswordDO selectByUserId(Integer userId);
步驟4:編寫(xiě)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) {
//調(diào)用service服務(wù)獲取對(duì)應(yīng)id的用戶對(duì)象并返回給前端
UserModel userModel = userService.getUserById(id);
return userModel;
}
}
運(yùn)行后,訪問(wèn)http://localhost:8090/user/get?id=1(需要事先添加好一條完整的數(shù)據(jù)),可以看到頁(yè)面上輸出了這條數(shù)據(jù)的完整信息。
步驟5:發(fā)現(xiàn)問(wèn)題:在UserController中,我們把userModel模型直接返回給前端,導(dǎo)致密碼直接輸出在頁(yè)面中,這是非常不專業(yè)的。
因此,我們?cè)赾ontroller層(包)中需要新建一個(gè)模型對(duì)象。在controller層中新建一個(gè)viewobject包,并在其中寫(xiě)一個(gè)viewobject類,里面只寫(xiě)需要展示在前端的字段與getters&setters。
1 package org.example.controller.viewobject;
2
3 public class UserVO {
4 //只寫(xiě)前端用戶所需要的信息
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 }
同時(shí),我們修改UserController類,將UserModel轉(zhuǎn)化為viewobject后,再返回給前端。
@Controller("user")
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/get")
@ResponseBody
public UserVO getUser(@RequestParam(name="id") Integer id) {
//調(diào)用service服務(wù)獲取對(duì)應(yīng)id的用戶對(duì)象并返回給前端
UserModel userModel = userService.getUserById(id);
//將核心領(lǐng)域模型對(duì)象轉(zhuǎn)化為可供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;
}
}
這一步中,我們做了一個(gè)完整的從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),展示在前端頁(yè)面上的操作。
controller層——>service層——>dao層
dataobject層負(fù)責(zé)數(shù)據(jù)存儲(chǔ)到service的傳輸,并且在用戶的service的服務(wù)中組裝了對(duì)應(yīng)的核心領(lǐng)域模型。
controller層做了到用戶viewobject之間的傳遞,保證密碼等信息不會(huì)輸出到前端。
2.定義通用的返回對(duì)象
步驟1:自主管理前端頁(yè)面的返回——返回正確信息
org.example包下創(chuàng)建一個(gè)response包,在其中創(chuàng)建一個(gè)CommonReturnType.java文件。
在該文件中,設(shè)置兩個(gè)屬性:status,data,并生成對(duì)應(yīng)的getters&setters。然后寫(xiě)兩個(gè)構(gòu)造方法,包含了兩個(gè)屬性的設(shè)置。
package org.example.response;
public class CommonReturnType {
//表名對(duì)應(yīng)請(qǐng)求的返回處理結(jié)果,success/fail
private String status;
//若status返回success,則data內(nèi)返回前端需要的json數(shù)據(jù)
//若status返回success,則data內(nèi)使用通用的錯(cuò)誤碼格式
private Object data;
//定義一個(gè)通用的創(chuàng)建方法
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調(diào)用create方法來(lái)引用UserVO中的信息。以下代碼為需要修改的部分:
public CommonReturnType getUser(@RequestParam(name="id") Integer id) {
//調(diào)用service服務(wù)獲取對(duì)應(yīng)id的用戶對(duì)象并返回給前端
UserModel userModel = userService.getUserById(id);
//將核心領(lǐng)域模型對(duì)象轉(zhuǎn)化為可供UI使用的viewobject
UserVO userVO = convertFromModel(userModel);
//返回通用對(duì)象
return CommonReturnType.create(userVO);
}
運(yùn)行后,我們?nèi)匀辉L問(wèn)http://localhost:8090/user/get?id=1,可以看到頁(yè)面上輸出了:

步驟2:自主管理前端頁(yè)面的返回——返回錯(cuò)誤信息
org.example包下創(chuàng)建一個(gè)error包,在其中創(chuàng)建一個(gè)CommonError接口,寫(xiě)3個(gè)方法:獲取錯(cuò)誤碼,獲取錯(cuò)誤信息,設(shè)置錯(cuò)誤信息
public interface CommonError {
public int getErrCode();
public String getErrMsg();
public CommonError setErrMsg(String errMsg);
}
error包下寫(xiě)一個(gè)枚舉類型的EmBusinessError,實(shí)現(xiàn)CommonError接口。
package org.example.error;
public enum EmBusinessError implements CommonError{
//通用錯(cuò)誤類型10001
PARAMETER_VALIDATION_ERROR(10001,"參數(shù)不合法"),
//未知錯(cuò)誤10002
UNKNOWN_ERROR(10002,"未知錯(cuò)誤"),
//20000開(kāi)頭相關(guān)為用戶信息相關(guān)錯(cuò)誤定義
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包下寫(xiě)一個(gè)BusinessException,實(shí)現(xiàn)CommonError接口,并繼承Exception類。
public class BusinessException extends Exception implements CommonError{
private CommonError commonError;
//直接接收EmBusinessError的傳參用于構(gòu)造業(yè)務(wù)異常
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中添加如下代碼:
//若獲取的對(duì)應(yīng)用戶信息不存在
if(userModel==null){
throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
}
步驟3:異常處理
在controller目錄下單獨(dú)寫(xiě)一個(gè)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<String,Object> 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類。
運(yùn)行后,我們?cè)L問(wèn)http://localhost:8090/user/get?id=2,(id=2的數(shù)據(jù)是不存在的),可以看到頁(yè)面為:

為了程序的健壯性,我們?cè)贐aseController中添加了一個(gè)unknown error。我們可以手動(dòng)地來(lái)測(cè)試一下這段代碼是否起了作用:
修改UserController部分代碼如下:
if(userModel==null){
userModel.setEncriptPassword("123");
//throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
}
運(yùn)行后,我們?cè)俅卧L問(wèn)http://localhost:8090/user/get?id=2,可以看到頁(yè)面為:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼
- Springboot+redis+Vue實(shí)現(xiàn)秒殺的項(xiàng)目實(shí)踐
- 基于Redis結(jié)合SpringBoot的秒殺案例詳解
- SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng))
- springboot集成redis實(shí)現(xiàn)簡(jiǎn)單秒殺系統(tǒng)
- springboot集成開(kāi)發(fā)實(shí)現(xiàn)商場(chǎng)秒殺功能
- 如何通過(guò)SpringBoot實(shí)現(xiàn)商城秒殺系統(tǒng)
- SpringBoot微服務(wù)實(shí)現(xiàn)秒殺搶購(gòu)代金券功能
相關(guān)文章
idea常用的18個(gè)設(shè)置(程序員必不可少)
這篇文章主要給大家介紹了關(guān)于idea常用的18個(gè)設(shè)置,這些對(duì)程序員們來(lái)說(shuō)必不可少,idea開(kāi)發(fā)常用基本且非常實(shí)用的配置,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
做java這么久了居然還不知道JSON的使用(一文帶你了解)
這篇文章主要介紹了做java這么久了居然還不知道JSON的使用(一文帶你了解),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
async-excel實(shí)現(xiàn)多sheet異步導(dǎo)出方法詳解
這篇文章主要介紹了async-excel實(shí)現(xiàn)多sheet異步導(dǎo)出方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12
Java實(shí)現(xiàn)將每日新聞添加到自己博客中
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)將每日新聞添加到自己博客中并發(fā)送到微信群中,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12
詳解 Corba開(kāi)發(fā)之Java實(shí)現(xiàn)Service與Client
這篇文章主要介紹了詳解 Corba開(kāi)發(fā)之Java實(shí)現(xiàn)Service與Client的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-10-10
Java實(shí)現(xiàn)inputstream流的復(fù)制代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)inputstream流的復(fù)制代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02

