本文將與大家一起使用SpringMVC開發獲取前端查詢用戶id查詢用戶信息的功能,其中不僅僅是把數據傳給前端,也會包括一些分層領域設計。
本文接着上一篇文章《SpringBoot快速整合Mybatis以及mybatis-generator的使用》繼續進行設計,爲避免產生疑惑,請先根據上一篇文章配置。本文按照DAO–>service–>Controller順序講解,實際開發可能有所不同。
1 DAO層
上一篇文章中,我們通過mybatis-generator分別生成了6個文件,分別是3對DO數據庫對象類、Mapper接口以及XML配置文件(例如,UserDO–UserDOMapper–UserDOMapper.xml)。
UserDO
public class UserDO {
private Integer id;
private String name;
private Byte gender;
private Byte age;
private String telephone;
private String registerMode;
private String thirdPartyId;
// getter and setter
}
UserPasswordDO
public class UserPasswordDO {
private Integer id;
private String encrptPassword;
private Integer userId;
// getter and setter
}
之前的數據庫設計中,出於安全等考慮,將用戶信息和用戶密碼分成了兩個表來存儲。其實兩者均爲用戶數據,因此我們會返回所有的數據給Service層做業務處理。
單純對於查詢用戶信息這個業務來說,我們分別根據用戶id從兩個表查出用戶基本信息和密碼。UserDO和UserPasswordDO在上一篇文章中創建好,本文沒有改變,僅需對Mapper接口和Mapper.xml做一些配置。
UserMapper接口和XML配置,mybatis-generator已經自動生成。
UserDO selectByPrimaryKey(Integer id);
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from seckill_user
where id = #{id,jdbcType=INTEGER}
</select>
UserPasswordMapper接口和XML配置
UserPasswordDO selectByUserId(Integer userId);
<select id="selectByUserId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from seckill_password
where id = #{userId,jdbcType=INTEGER}
</select>
2 Service層
上節DAO層完成了數據庫數據映射的一些操作。Service層對DAO層數據封裝成Model模型。Model層面纔是真正意義上處理業務的核心模型,而Dataobject僅僅作爲數據庫的映射。
UserModel
public class UserModel {
private Integer id;
private String name;
private Byte gender;
private Byte age;
private String telephone;
private String registerMode;
private String thirdPartyId;
private String encrptPassword;
// getter and setter
}
Service接口–UserService
public interface UserService {
UserModel getUserById(Integer id);
}
Service接口實現–UserServiceImpl
@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;
}
UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
if (userPasswordDO == null) {
return null;
}
return convertFromDataObject(userDO, userPasswordDO);
}
private UserModel convertFromDataObject(UserDO userDO, UserPasswordDO userPasswordDO) {
UserModel userModel = new UserModel();
BeanUtils.copyProperties(userDO, userModel);
// 此處不能用copyProperties()方法,兩個dataobject對象中重複字段id
userModel.setEncrptPassword(userPasswordDO.getEncrptPassword());
return userModel;
}
}
3 Controller層
上節中Service層已經對DAO層數據根據業務需求做了加工,並返回了Model。直接通過Controller層輸出UserModel模型對象,我們會得到下面結果。
啓動SpringBoot服務,訪問http://localhost:8080/user/get?id=1。
{
"id": 1,
"name": "首位用戶",
"gender": 1,
"age": 18,
"telephone": "18611001100",
"registerMode": "bywechat",
"thirdPartyId": "wechatnum",
"encrptPassword": "encrptpassword1234"
}
首先,根據用戶id獲取用戶信息的業務需求已經滿足了。但是,這樣做會不規範的,會把不必要或者不安全的數據返回給前端,例如後三個字段:登錄方式、用戶第三方ID、用戶密碼,既沒有必要,還可能帶來風險。因此,我們需要在Controler層在Service層返回Model對象的基礎上再封裝一層對象VO。
UserVO
public class UserVO {
private Integer id;
private String name;
private Byte gender;
private Byte age;
private String telephone;
// getter and setter
}
UserController 代碼實現
@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;
}
}
4 測試運行
此時,我們已經完成了DAO層、Service層、Controller層代碼開發,代碼目錄結構如下。
啓動SpringBoot服務,訪問http://localhost:8080/user/get?id=1 ,得到如下對象。
{
"id": 1,
"name": "首位用戶",
"gender": 1,
"age": 18,
"telephone": "18611001100"
}