Service層的接口中有一些比較常用方法,一次又一次的在新的Service層中被書寫,所以懶惰的程序員又煩了,他們決定寫個通用接口來解決這個問題。
有些項目中,實體類即承擔接收表單數據的任務,又承擔持久化任務,很省心。但有些項目中這兩項任務的執行類不是同一個,一個Entity.java來執行數據
持久化的任務,一個EntityVo.java類來執行接收表單數據的任務。那么問題來了:Service層需要的是entityVo對象,而DAO層需要的是entity對象,這兩個對象
會有一些相同的屬性和方法,也會有一些不同的屬性和方法,那么在service層中必然要做entityVo對象到entity對象的轉換工作,而這項工作又不屬於業務。如果
處理方法與業務混在一起寫,代碼的清晰度就會受到影響。所以本文中做了這方面的處理,可能並不是最好的方案,但起碼比沒有處理要好的多。
BaseService.java
package org.lxl.mr.common.base.service;
import java.util.List;
public interface BaseService<EntityVo,PK> {
/**
* 增加
* @param entityVo
*/
public void save(EntityVo entityVo);
/**
* 修改
* @param entityVo
*/
public void update(EntityVo entityVo);
/**
* 通過主鍵刪除
* @param pk
*/
public void deleteByPK(PK pk);
/**
* 刪除
* @param entityVo
*/
public void delete(EntityVo entityVo);
/**
* 通過主鍵查詢
* @param pk
* @return
*/
public EntityVo get(PK pk);
/**
* 查詢全部
* @return
*/
public List<EntityVo> findAll();
}
使用
UserService.java
package org.lxl.mr.service;
import org.lxl.mr.common.base.service.BaseService;
import org.lxl.mr.vo.UserVo;
public interface UserService extends BaseService<UserVo, String>{
}
這個處理非常簡單,就是寫個父接口,把常用的方法寫在父接口中,子接口沒有其他的需要就什么都不用寫;有
其他的需要就再寫相應的方法即可。
BaseServiceImpl.java
package org.lxl.mr.common.base.service;
import org.lxl.mr.common.base.vo.VoTemplate;
import org.springframework.beans.factory.annotation.Autowired;
public class BaseServiceImpl {
private VoTemplate voTemplate;
@Autowired
public final void setVoTemplate(VoTemplate voTemplate) {
this.voTemplate = voTemplate;
}
public final VoTemplate getVoTemplate(){
return this.voTemplate;
}
}
這個通用方法並不是用來自動實現BaseService接口中的方法的,而是處理entityVo和entity直接轉化的問題的。
這是仿造HibernateDaoSupport的寫法,注入voTemplate對象。其中voTemplate的get/set方法都是final修飾的,
是不允許子類重寫的,保證了注入的正確執行。
VoTemplate.java
package org.lxl.mr.common.base.vo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
/**
* 本類的作用是解決service層傳遞的EntityVo對象與dao層
* 使用的Entity對象轉換的問題,更輕松,更規范的處理該問題
* @author liuXueLiang
*/
@Component
public class VoTemplate {
/**
* 由程序員自己提供一個回調方法
* @param vo
* @return
*/
public <T> T execute(VoCallback<T> vo){
return vo.doInVo();
}
/**
* 默認的回調方法,將v的屬性值復制給t,並將t返回
* @param t 回調對象
* @param v 目標對象
* @return
*/
public <T,V> T defaultExcute(final T t,final V v){
return this.execute(new VoCallback<T>(){
@Override
public T doInVo() {
if(v==null) return null;
BeanUtils.copyProperties(v,t);
return t;
}
});
}
}
VoCallback.java
package org.lxl.mr.common.base.vo;
public interface VoCallback<T> {
T doInVo();
}
使用
package org.lxl.mr.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.lxl.mr.common.base.service.BaseServiceImpl;
import org.lxl.mr.common.base.vo.VoCallback;
import org.lxl.mr.dao.UserDao;
import org.lxl.mr.pojo.User;
import org.lxl.mr.service.UserService;
import org.lxl.mr.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 增加,方法一
*/
@Override
public void save(UserVo entityVo) {
User user = new User();
user = super.getVoTemplate().defaultExcute(user, entityVo);
this.userDao.save(user);
}
/**
* 增加,方法二
*/
// @Override
// public void save(final UserVo entityVo) {
//
// //這里是處理entityVo與entity轉換的地方
// User user = super.getVoTemplate().execute(new VoCallback<User>(){
//
// @Override
// public User doInVo() {
// User u = new User();
// //這句根據主鍵生成策略決定要、不要、改
// u.setUuid(UUID.randomUUID().toString().replace("-", ""));
// u.setUsername(entityVo.getUsername());
// u.setPassword(entityVo.getPassword());
// return u;
// }
//
// });
//
// //處理業務
// this.userDao.save(user);
// }
/**
* 增加,方法三
*/
// @Override
// public void save(UserVo entityVo) {
// //這里是處理entityVo與entity轉換的地方
// User user = super.getVoTemplate().execute(new UserVoCallback(entityVo));
// //這里是處理業務的地方
// this.userDao.save(user);
// }
/**
* 增加,方法四
*/
// @Override
// public void save(UserVo entityVo) {
// //這里是處理entityVo與entity轉換的地方
// User user = super.getVoTemplate().execute(new UserVoCallback2(entityVo));
// //這里是處理業務的地方
// this.userDao.save(user);
// }
@Override
public void update(UserVo entityVo) {
User user = new User();
user = super.getVoTemplate().defaultExcute(user, entityVo);
this.userDao.update(user);
}
public UserDao getUserDao() {
return userDao;
}
@Override
public void deleteByPK(String pk) {
this.userDao.deleteByPK(pk, UserVo.PK_NAME);
}
@Override
public void delete(UserVo entityVo) {
User user = new User();
user = super.getVoTemplate().defaultExcute(user, entityVo);
this.userDao.delete(user);
}
@Override
public UserVo get(String pk) {
User user = this.userDao.get(pk);
UserVo userVo = new UserVo();
userVo = super.getVoTemplate().defaultExcute(userVo,user);
return userVo;
}
@Override
public List<UserVo> findAll() {
List<User> list = this.userDao.findAll();
List<UserVo> listVo = new ArrayList<UserVo>();
if(list==null) return null;
for(User user : list){
UserVo userVo = new UserVo();
userVo = super.getVoTemplate().defaultExcute(userVo, user);
listVo.add(userVo);
}
return listVo;
}
}
上面的例子以save方法為例,給出了voTemplate處理entityVo與entity轉化的4種用法。
方法1
使用voTemplate的defaultExcute方法,簡單的從 v -> t 復制屬性
方法2
使用voTemplate的excute方法,自定義處理方法。
方法2、3、4都是自定義處理方法,只不過在提供VoCallback<T>的實現類方式上有所差別。
這里是用內部類實現的
方法3
提供一個UserVoCallback.java,實現VoCallback接口。
以這個類的對象作為voTemplate.execute的參數來實現的。
UerVoCallback.java
package org.lxl.mr.vo.callback;
import org.lxl.mr.common.base.vo.VoCallback;
import org.lxl.mr.pojo.User;
import org.lxl.mr.vo.UserVo;
public class UserVoCallback implements VoCallback<User> {
private UserVo userVo;
public UserVoCallback(UserVo userVo){
this.userVo = userVo;
}
@Override
public User doInVo() {
if(userVo==null) return null;
User user = new User();
user.setUsername(userVo.getUsername());
user.setPassword(userVo.getPassword());
return user;
}
}
方法4
1) 提供一個VoCallback接口的抽象實現類VoCallbackSupport.java:
VoCallbackSupport.java
package org.lxl.mr.common.base.vo;
public abstract class VoCallbackSupport<T,V> implements VoCallback<T> {
protected V v;
public VoCallbackSupport(V v){
this.v = v;
}
@Override
public abstract T doInVo();
}
2)提供一個UserVoCallback2.java,繼承VoCallbackSupport抽象類。
以這個類的對象作為voTemplate.execute的參數來實現的。
UserVoCallback2.javapackage org.lxl.mr.vo.callback;
import org.lxl.mr.common.base.vo.VoCallbackSupport;
import org.lxl.mr.pojo.User;
import org.lxl.mr.vo.UserVo;
public class UserVoCallback2 extends VoCallbackSupport<User, UserVo>{
public UserVoCallback2(UserVo v) {
super(v);
}
@Override
public User doInVo() {
User user = new User();
user.setUsername(v.getUsername());
user.setPassword(v.getPassword());
return user;
}
}
這種方式處理entityVo與entity之間轉換與傳統的方式一樣,還是要程序員自己去處理。
它真正的好處是:
1、規范化處理entityVo與entity之間的轉換
2、處理entityVo與entity之間轉換的代碼與業務代碼分離,使代碼更清晰
3、在entityVo與entity相似度極高,可以直接復制相同屬性的情況下,使用VoTemplate
提供的defalutExcute方法一句話即可實現entityVo與entity的轉換,如:
User user = super.getVoTemplate().defaultExcute(new User,entityVo);
非常的方便!
覺得我的這個方案可行的小伙伴不妨在項目中用用,有更好的想法記得告訴我,我們一起提高!