友快網

導航選單

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

專案介紹:

(1)功能介紹:

主要業務:為公司活動(如年會等)提供線上抽獎功能,滿足獎品、抽獎人員的管理,及抽獎活動的需要。

使用者註冊

使用者登入、會話管理

抽獎設定:獎品管理,抽獎人員管理

人員抽獎

(2)開發環境與技術棧:

windows

Maven

Lombok

Spring、SpringMVC、SpringBoot

MySQL、Mybatis、Druid

(3)專案演示:

使用者登入:

使用者註冊:

獎項設定:

抽獎人員設定:

抽獎:

2、專案準備:

(1)程式碼框架:(原始碼)

(2)資料庫設計:

資料庫表關係圖:

(業務上一對一)

為什麼要有設定表?

1對1關聯的表,其實可以只使用1張表儲存所有欄位;但是在一些可能出現的業務擴充套件,方便系統擴充套件使用,所以設計表時,考慮1對1設計。

拓展業務 ,一個使用者進來設定,當多個使用者進來設定的時候(多個使用者屬於同一公司),如果是隻有使用者表的話,即無法支撐業務,使用者表關聯公司,設定表在關聯公司

3、後端對前端介面的實現:

要實現功能,需要先明確前後端約定好的介面。需要說明的是,介面的定義一般是前後端約定好的,所以也和前端程式碼息息相關,前端需要什麼資料,需要什麼格式的資料,也會在介面中體現。

介面主要體現在:

請求需要的資訊:請求方法,請求路徑,請求資料

響應資料

(1)使用者的登入、註冊、登出

使用者登入:

前端請求:

POST api/user/login (請求路徑)

Content-Type: application/json {username: “qbs”, password: “123”}

響應:

{ “success” : true }

後端實現介面:

使用者註冊:

前端請求:

POST api/user/register (請求路徑)

Content-Type: multipart/form-data; boundary=—— WebKitFormBoundarypOUwkGIMUyL0aOZT

username: qbs

password: 123

nickname: 帥哥

email: 666@163。com

age: 18

headFile: (binary)

響應:

{ “success” : true }

後端實現:

使用者登出:

前端請求:

POST api/user/login (請求路徑)

後端實現:

(2)查詢獎項設定、修改抽獎人數:

查詢獎項設定:

前端請求:

GET api/setting/query(請求路徑)

後端實現:

修改抽獎人數:

前端請求:

GET api/setting/update?batchNumber=5(請求路徑)

(介面對應抽獎設定頁面中,點每次抽獎人數下拉選單切換時修改)

後端實現:

(3)新增、修改、刪除獎項:

新增獎項:

前端請求:

POST api/award/add (請求路徑)

Content-Type: application/json

{name: “特等獎”, count: 1, award: “全球旅行7日遊”}

後端實現:

修改獎項:

前端請求:

POST api/award/update (請求路徑)

Content-Type: application/json

後端響應:

刪除獎項:

前端請求:

GET api/award/delete/4(請求路徑)

最後的數字4,對應獎項的id

後端實現:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

(4)新增、修改、刪除抽獎人員:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

新增抽獎人員:

前端請求:

POST api/member/add (請求路徑)

Content-Type: application/json

後端實現:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

修改抽獎人員

前端請求:

POST api/member/update

Content-Type: application/json

後端實現:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

刪除抽獎人員

前端請求:

GET api/member/delete/97

(最後的數字為抽獎人員的id)

後端實現:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

(5)抽獎、刪除獲獎人員:

抽獎:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

前端請求:

POST api/record/add/3

Content-Type: application/json

(以上路徑中最後的數字代表獎項id,請求資料為抽獎人員id組成的陣列)

後端實現:

抽獎後端只是插入記錄(人員id、獎項id),具體的抽獎是前端實現的,而且也是簡單的實現方式,沒有任何演算法。(只是在當前獎項剩餘名額中,每次抽獎人數,在所有未中獎的人員列表中,隨機抽取)

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

刪除獲獎人員:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

前端請求:

GET api/record/delete/member?id=22

(根據 人員id 刪除對應的獲獎記錄)

GET api/record/delete/award?id=3

(根據 獎項id 刪除對應所有獲獎人員記錄)

後端實現:

阿里架構師用Java語言實現抽獎專案系統,已在GitHub 星標超 4萬

4、程式碼設計:

(1)設計資料庫的實體類:

透過 mybatis 生成工具(tool包):生成 mapper、資料庫表實體類(model包)、xml 檔案

(2)設計統一響應類:

主要是為了返回資料的統一欄位設計

/**

* 統一響應的資料格式

*/

public class JSONResponse {

private boolean success;

private String code;

private String message;

private Object data;

}

/**

* 統一資料封裝

*/

public class RequestResponseBodyMethodProcessorWrapper implements HandlerMethodReturnValueHandler {

private final HandlerMethodReturnValueHandler delegate;

public RequestResponseBodyMethodProcessorWrapper(HandlerMethodReturnValueHandler delegate) {

this。delegate = delegate;

}

@Override

public boolean supportsReturnType(MethodParameter returnType) {

return delegate。supportsReturnType(returnType);

}

@Override

public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

//returnValue是Controller請求方法執行完,返回值

if(!(returnValue instanceof JSONResponse)){//返回值本身就是需要的型別,不進行處理

JSONResponse json = new JSONResponse();

json。setSuccess(true);

json。setData(returnValue);

returnValue = json;

}

delegate。handleReturnValue(returnValue, returnType, mavContainer, webRequest);

}

}

(3)設計自定義異常:

主要針對不同的場景,需要拋異常來處理時,能定位業務含義。

主要分為:

1、 客戶端請求錯誤時的異常:需要給定錯誤碼,方便前端提示使用者,如使用者名稱存在不允許註冊

2、 業務發生錯誤時的異常:需要給定錯誤碼,方便後端定位問題,一般如程式上的業務錯誤都可以拋(BUG)

3、 系統發生錯誤時的異常:需要給定錯誤碼,方便後端定位問題,程式出錯,如資料庫連接獲取失敗都可以拋(一般是系統發生錯誤,如網路斷了,資料庫掛了等等)自定義異常前端需要顯示錯誤碼和錯誤訊息,使用者可以根據提示資訊判斷原因。

4、非自定義異常,異常資訊一般是框架或JDK丟擲的英文,是給開發人員描述錯誤的,無法給使用者提示,所以錯誤資訊提示為未知異常。

/**

* 自定義異常:儲存錯誤碼和錯誤訊息

*/

@Getter

@Setter

public class AppException extends RuntimeException {

private String code;

public AppException( String code, String message) {

super(message);

this。code = code;

}

public AppException( String code, String message, Throwable cause) {

super(message, cause);

this。code = code;

}

}

//統一異常處理

@ControllerAdvice

@Slf4j//使用lombok日誌日誌註解,之後使用log屬性來完成日誌列印

public class ExceptionAdvice {

//自定義異常報錯錯誤碼和錯誤訊息

@ExceptionHandler(AppException。class)

@ResponseBody

public Object handle1(AppException e){

JSONResponse json = new JSONResponse();

json。setCode(e。getCode());

json。setMessage(e。getMessage());

log。debug(“自定義異常”, e);

return json;

}

//非自定義異常(英文錯誤資訊,堆疊資訊,不能給使用者看):

// 指定一個錯誤碼,錯誤訊息(未知錯誤,請聯絡管理員)

@ExceptionHandler(Exception。class)

@ResponseBody

public Object handle2(Exception e){

JSONResponse json = new JSONResponse();

json。setCode(“ERR000”);

json。setMessage(“未知錯誤,請聯絡管理員”);

log。error(“未知錯誤”, e);

return json;

}

}

(4)設計統一會話管理的攔截器

public class LoginInterceptor implements HandlerInterceptor {

private ObjectMapper objectMapper;

public LoginInterceptor(ObjectMapper objectMapper) {

this。objectMapper = objectMapper;

}

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

HttpSession session = request。getSession(false);

if(session != null){//獲取登入時設定的使用者資訊

User user = (User) session。getAttribute(“user”);

if(user != null){//登入了,允許訪問

return true;

}

}

//登入失敗,不允許訪問的業務:區分前後端

//TODO:前端跳轉登入頁面,後端返回json

//        new ObjectMapper()。writeValueAsString(object);//序列化物件為json字串

//請求的服務路徑

String servletPath = request。getServletPath();//   /apiXXX。html

if(servletPath。startsWith(“/api/”)){//後端邏輯:返回json

response。setCharacterEncoding(“UTF-8”);

response。setContentType(MediaType。APPLICATION_JSON_VALUE);

JSONResponse json = new JSONResponse();

json。setCode(“USR000”);

json。setMessage(“使用者沒有登入,不允許訪問”);

String s = objectMapper。writeValueAsString(json);

response。setStatus(HttpStatus。UNAUTHORIZED。value());

PrintWriter pw = response。getWriter();

pw。println(s);

pw。flush();

}else{//前端邏輯:跳轉到登入頁面 /views/index。html

//相對路徑的寫法,一定是請求路徑作為相對位置的參照點

//使用絕對路徑來重定向,不建議使用相對路徑和轉發

String schema = request。getScheme();//http

String host = request。getServerName();//ip

int port = request。getServerPort();//port

String contextPath = request。getContextPath();//application Context path應用上下文路徑

String basePath = schema+“://”+host+“:”+port+contextPath;

//重定向到登入頁面

response。sendRedirect(basePath+“/index。html”);

}

return false;

}

}

(5)設計Mybatis中Mapper的基類:

使用Mybatis的介面方法,所有介面方法都是類似,只是傳入引數和返回值不同,可以考慮設計統一的基類,以泛型的方式定義出不同的引數型別、返回型別

/**

* 所有 mapper 父介面

*/

public interface BaseMapper {

int deleteByPrimaryKey(Integer id);

int insert(T record);

int insertSelective(T record);

T selectByPrimaryKey(Integer id);//透過主鍵查詢

int updateByPrimaryKeySelective(T record);//根據主鍵修改其他非主鍵欄位

int updateByPrimaryKey(T record);

}

上一篇:美國火星照片是“造假”?網友拿出關鍵證據,與加拿大山峰相同
下一篇:用無用的道理,道德經早就說過,看起來沒有用的才是有用處