01.16 Spring Boot合理使用接口對業務代碼和邏輯代碼進行分離

前言

未標準化進行java開發時,沒有進行對業務代碼以及公用邏輯進行分離,如果需求遇到改動,需要改公用邏輯時,需要去一處處業務代碼中去找,大大的浪費了時間,使用接口後,可以合理的解決這一問題。

接口的概念

  • 使用interface聲明的類
  • 只有方法標識符,沒有方法體
  • 接口像藍圖一樣,指明一個類必須要做什麼和不能做什麼
  • 接口中所有的方法都是抽象的和public的,所有的屬性都是public,static,final的。
  • 一個類如果要實現某個接口時,必須要實現這個接口中的所有方法。

接口的作用

  • 實現多繼承:因為Java不能像c++一樣支持多繼承,Java可以通過實現接口來彌補這個問題。
  • 接口可以解偶
  • 可以將邏輯代碼與業務代碼進行分

接口的語法

  • 使用interface聲明一個類,在類內聲明一個註冊方法
<code>public interface UserService { 

// 新用戶註冊接口
public Integer AddUser(String userName,String userId,String password,String avatarSrc,String createTime);
}/<code>
  • 創建接口實現類,使用Override重寫AddUser方法
<code>// 實現註冊接口
@Override
public Integer AddUser(String userName, String userId, String password, String avatarSrc, String createTime) {
User row = new User();
row.setUserName(userName);
row.setUserId(userId);
row.setPassword(password);
row.setAvatarSrc(avatarSrc);
row.setCreateTime(createTime);
// 增加用戶,向數據庫插入一條數據
return userMapper.insertUser(row);
}/<code>

實際應用

我們先來看看不使用接口時,將功能的實現和業務代碼全寫在controller層的代碼,這裡我們以登錄為例,如果遇到新的需求,我們就要去找找功能實現部分進行修改,業務代碼過多時是一件很頭疼的事情

<code>@RestController
@RequestMapping("/user")
public class GreetingController {
private final Logger logger= LoggerFactory.getLogger(getClass());
@Resource
private UserInfoMapper userMapper;
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@CrossOrigin()
// 登錄請求

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@RequestBody String request){
// 獲取前端參數
JSONObject jsReq = new JSONObject(request);
JSONObject jsReply = new JSONObject();
String username = jsReq.getString("username");
String password = jsReq.getString("password");
UserInfo row = new UserInfo();
JSONArray queryType = new JSONArray();
queryType.put("name");
queryType.put("password");
queryType.put("career");
queryType.put("avatarSrc");
queryType.put("userID");
row.setQueryType(queryType);
row.setName(username);
List<userinfo> resultList = userMapper.customQuery(row);
JSONArray result = null;
if(resultList.size()>0){
result = new JSONArray(resultList);
if(password.equals(result.getJSONObject(0).getString("password"))){
jsReply.put("code",0);
// 根據當前用戶名和密碼生成token
jsReply.put("token", JwtUtil.sign(username,password));
jsReply.put("msg","驗證成功,token有效期為30分鐘");
jsReply.put("avatarSrc",result.getJSONObject(0).getString("avatarSrc"));
jsReply.put("userID",result.getJSONObject(0).getString("userID"));
}else{
jsReply.put("code",-2);
jsReply.put("msg","密碼錯誤");
}
}else{
jsReply.put("code",-1);
jsReply.put("msg","當前登錄用戶不存在");
}
return jsReply.toString();
}

}/<userinfo>/<code>
  • 使用接口對上述場景的代碼進行分離(這裡我們以註冊功能為例)
<code>// service層
package com.lk.service;

public interface UserService {
// 新用戶註冊接口
public Integer AddUser(String userName,String userId,String password,String avatarSrc,String createTime) throws Exception;
}/<code>
<code>// serviceimpl層(接口實現)
package com.lk.serviceimpl;

import com.lk.dao.UserMapper;
import com.lk.entity.User;
import com.lk.service.UserService;
import com.lk.utils.HMacMD5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
private final Logger logger= LoggerFactory.getLogger(getClass());
// 從配置文件讀取加密key
@Value("${HMacKey}")
private String HMacKey;
// 實現註冊接口
@Override
public Integer AddUser(String userName, String userId, String password, String avatarSrc, String createTime) throws Exception {
// 判斷參數是否合法
if(userName.equals("")||userName.length()>10){
logger.error("違規操作:用戶名為空或用戶名長度大於10,"+userName);
return -1;
}else if(password.equals("")||password.length()>16){
logger.error("違規操作:密碼為空或密碼長度大於10,"+password);
return -2;
}else if(avatarSrc.equals("")||avatarSrc.length()>300){

logger.error("違規操作:頭像地址為空或頭像地址過長,"+avatarSrc);
return -3;
}
// 對密碼進行加密
password = HMacMD5.encryptHMAC2String(password,HMacKey);
User row = new User();
row.setUserName(userName);
row.setUserId(userId);
row.setPassword(password);
row.setAvatarSrc(avatarSrc);
row.setCreateTime(createTime);
logger.info(userMapper+"");
// 增加用戶,向數據庫插入一條數據
int result = userMapper.insertUser(row);
logger.info(result+"");
return result;
}
}/<code>
<code>// controller層(業務代碼)
package com.lk.controller;

import com.lk.dao.UserMapper;
import com.lk.serviceimpl.UserServiceImpl;
import com.lk.utils.DateUtil;
import com.lk.utils.UUIDUtil;
import com.lk.utils.UnifiedReturnDataUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@RequestMapping("/api/user")
public class UserController {
@Resource
private UserMapper userMapper;
@Resource(name = "userServiceImpl")
private UserServiceImpl userService;
private final Logger logger= LoggerFactory.getLogger(getClass());


@RequestMapping(value = "/registered", method = RequestMethod.POST)
public String login(@RequestBody String request) throws Exception {
// 生成userId
String userId = UUIDUtil.getUUID();
// 生成註冊日期
String createTime = DateUtil.getThisTime();
// 序列化前端參數
JSONObject jsReq = new JSONObject(request);
// 實例化註冊服務
// UserServiceImpl userService = new UserServiceImpl();
// 調用註冊接口
int result = userService.AddUser(jsReq.getString("userName"),userId,jsReq.getString("password"),jsReq.getString("avatarSrc"),createTime);
JSONArray responseData = new JSONArray();
// 判斷是否註冊成功
if(result>0){
return UnifiedReturnDataUtil.returnJSONString(result,"註冊成功",responseData);
}
return UnifiedReturnDataUtil.returnJSONString(result,"註冊失敗",responseData);
}
}/<code>

踩坑記錄

在controller層使用接口實現類裡的方法時,spring註解的內容一直為null,無法拿到@Resource註解的mybatis裡的mapper對象和@Value註解的獲取yml文件中的屬性,接口實現類報空指針異常。 原因是:我在controller層實例化接口實現類時,對象是自己new的,沒有走spring,所以一直為null。找了很多解決方案,走了很多彎路,最終使用@Service註解和@Resource註解完美解決了這個問題。 我的問題可以描述為:接口的實現類在controller層如何注入

  • 在controller層自己new接口實現類對象
<code>// 錯誤的解決方案,實現類不走spring容器,報空指針異常
UserServiceImpl userService = new UserServiceImpl();/<code>
  • 在接口實現類中使用@service註解,在controller層使用@Resource注入
<code>// 這裡括號中的名字為當前類名首字母小寫
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
/////++++++++++++++++++++++++/////
}/<code>
<code>// controller層
public class UserController {
// 括號裡的name值對應接口實現類@Service註解括號裡的名字
@Resource(name = "userServiceImpl")
private UserServiceImpl userService;
}/<code>

至此,關於接口實現類在controller層如何注入的問題就完美解決了,帶大家看下上述註冊接口實現的效果

Spring Boot合理使用接口對業務代碼和邏輯代碼進行分離

Spring Boot合理使用接口對業務代碼和邏輯代碼進行分離

鏈接:https://juejin.im/post/5e1fed4351882526945f46e


分享到:


相關文章: