项目中代码做了很多if-else判断,后期如果新增角色权限的话,不利于后期的维护,所以就做了一个优化。
通过获取登陆人的角色和other字段,判断登陆人可以看到哪些借款单,以及对可以看到的借款单拥有什么操作权限。
优化前的代码如下:
public JSONObject selectLoanList(SubAndApp subAndApp, String supplierName, String state, Long startTime, Long endTime, String currency, String submitter, Integer limit, Integer offset) {
Date st = null;
Date et = null;
if (startTime!=null&&endTime!=null) {
st = longToDate(startTime);
et = longToDate(endTime);
}
List<Loan> loanList = new ArrayList<>();
int count = 0;
if (subAndApp.getType()==SubAndApp.SubType.SUBMITTER) {
Integer other = subAndApp.getOther();
if (other==0) {
loanList = loanMapper.selectListBySubmitter(subAndApp.getSubEmail(), supplierName,
state, st, et, currency, submitter, limit, offset);
for (Loan loan : loanList) {
getSubmitAuth(loan);
}
count = loanMapper.selectCountBySubmitter(subAndApp.getSubEmail(), supplierName,
state, st, et, currency, submitter);
} else if (other==1) {
loanList = loanMapper.selectListByApplicant(subAndApp.getEid(),supplierName,
state, st, et, currency, submitter, limit, offset,subAndApp.getSubEmail());
for (Loan loan : loanList) {
getApplicantAuth(subAndApp, loan);
}
count = loanMapper.selectCountByApplicant(subAndApp.getEid(),supplierName,
state, st, et, currency, submitter,subAndApp.getSubEmail());
} else if (other==2) {
loanList = loanMapper.selectAllByAuditor(supplierName,
state, st, et, currency, submitter, limit, offset,subAndApp.getSubEmail());
for (Loan loan : loanList) {
getAuditorAuth(subAndApp, loan);
}
count = loanMapper.selectAllCountByAuditor( supplierName,
state, st, et, currency, submitter,subAndApp.getSubEmail());
} else if (other==3) {
loanList = loanMapper.selectAllByPrint( supplierName,
state, st, et, currency, submitter, limit, offset,subAndApp.getSubEmail());
for (Loan loan : loanList) {
getSubmitAuth(loan);
}
count = loanMapper.selectAllCountByPrint( supplierName,
state, st, et, currency, submitter,subAndApp.getSubEmail());
}
} else if (subAndApp.getType()==SubAndApp.SubType.AUDITOR) {
loanList = loanMapper.selectByAuditor( supplierName,
state, st, et, currency, submitter, limit, offset);
for (Loan loan : loanList) {
getAuditorAuth(subAndApp, loan);
}
count = loanMapper.selectCountByAuditor( supplierName,
state, st, et, currency, submitter);
} else if (subAndApp.getType()==SubAndApp.SubType.APPROVER) {
loanList = loanMapper.selectAllByApprover(supplierName,
state, st, et, currency, submitter, limit, offset);
for (Loan loan : loanList) {
getApproverAuth(loan);
}
count = loanMapper.selectAllCountByApprover(supplierName,
state, st, et, currency, submitter);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("list",loanList);
jsonObject.put("count",count);
return jsonObject;
}
优化后的代码如下:
思想是运用工厂模式和多态来优化代码
优化后的service层代码大大简化:
public JSONObject selectLoanList(SubAndApp subAndApp, String supplierName, String state, Long startTime, Long endTime, String currency, String submitter, Integer limit, Integer offset) {
AbstractAuthExecutor executor = AuthExcutorFactory.executor(subAndApp,loanMapper);
if (executor != null) {
return executor.getList(subAndApp,supplierName,state,startTime,endTime,currency,submitter,limit,offset);
}
else {
return null;
}
}
抽象父类如下:
@Component
public abstract class AbstractAuthExecutor {
@Autowired
LoanMapper loanMapper;
JSONObject jsonObject = new JSONObject();
List<Loan> loanList = new ArrayList<>();
int count = 0;
Date st = null;
Date et = null;
public JSONObject getList(SubAndApp subAndApp, String supplierName, String state, Long startTime, Long endTime, String currency, String submitter, Integer limit, Integer offset) {
return null;
}
/**
* 时间戳转换成date
* @param time
* @return
*/
protected Date longToDate(Long time){
return new Date(time);
}
/**
* 提交人权限
* @param loan
*/
protected void getSubmitAuth(Loan loan) {
List<String> authList = new ArrayList<>();
authList.add(Auth.DETAIL);
if (loan.getState()== Loan.LoanState.WAIT_COMMIT) {
authList.add(Auth.EDIT);
authList.add(Auth.DELETE);
} else if (loan.getState()== Loan.LoanState.WAIT_CHECK) {
authList.add(Auth.CANCEL);
} else if (loan.getState()== Loan.LoanState.NO_CHECK||loan.getState()== Loan.LoanState.NO_APPROVE) {
authList.add(Auth.EDIT);
} else if (loan.getState()== Loan.LoanState.APPROVED) {
authList.add(Auth.PRINT);
}
loan.setAuth(authList);
}
/**
* 提交人和申请人为同一人权限
* @param subAndApp
* @param loan
*/
protected void getApplicantAuth(SubAndApp subAndApp, Loan loan) {
List<String> authList = new ArrayList<>();
if (!loan.getEmail().equals(subAndApp.getSubEmail())) {
authList.add(Auth.DETAIL);
loan.setAuth(authList);
}else {
getSubmitAuth(loan);
}
}
/**
* 提交人拥有审核权限
* @param subAndApp
* @param loan
*/
protected void getAuditorAuth(SubAndApp subAndApp, Loan loan) {
List<String> authList = new ArrayList<>();
//自己的单子待审核状态的判断
if (loan.getState() == Loan.LoanState.WAIT_CHECK && loan.getEmail().equals(subAndApp.getSubEmail())) {
authList.add(Auth.CHECK);
authList.add(Auth.CANCEL);
authList.add(Auth.DETAIL);
loan.setAuth(authList);
//其他人的单子待审核状态的判断
}else if(loan.getState() == Loan.LoanState.WAIT_CHECK && !loan.getEmail().equals(subAndApp.getSubEmail())){
authList.add(Auth.CHECK);
authList.add(Auth.DETAIL);
loan.setAuth(authList);
//其他人的单子的其他状态判断
} else if(!loan.getEmail().equals(subAndApp.getSubEmail())){
authList.add(Auth.DETAIL);
loan.setAuth(authList);
} else {
getSubmitAuth(loan);
}
}
/**
* 审批权限
* @param loan
*/
protected void getApproverAuth(Loan loan) {
List<String> authList = new ArrayList<>();
authList.add(Auth.DETAIL);
if (loan.getState() == Loan.LoanState.WAIT_APPROVE) {
authList.add(Auth.APPROVE);
}
loan.setAuth(authList);
}
}
子类重写抽象父类中的getList方法,这里以审批者为例:
@Component
public class OnlyApproverExcutor extends AbstractAuthExecutor {
private final LoanMapper loanMapper;
@Autowired
public OnlyApproverExcutor(LoanMapper loanMapper) {
this.loanMapper = loanMapper;
}
@Override
public JSONObject getList(SubAndApp subAndApp, String supplierName, String state, Long startTime, Long endTime, String currency, String submitter, Integer limit, Integer offset) {
if (startTime != null && endTime != null) {
st = longToDate(startTime);
et = longToDate(endTime);
}
loanList = loanMapper.selectAllByApprover(supplierName,
state, st, et, currency, submitter, limit, offset);
for (Loan loan : loanList) {
getApproverAuth(loan);
}
count = loanMapper.selectAllCountByApprover(supplierName,
state, st, et, currency, submitter);
JSONObject jsonObject = new JSONObject();
jsonObject.put("list", loanList);
jsonObject.put("count", count);
return jsonObject;
}
}
工厂类如下:
@Component
public class AuthExcutorFactory {
public static AbstractAuthExecutor executor(SubAndApp subAndApp, LoanMapper loanMapper){
if (subAndApp.getType()==SubAndApp.SubType.SUBMITTER && subAndApp.getOther() == 0) {
return new OnlySubmitterExcutor(loanMapper);
}
if (subAndApp.getType()==SubAndApp.SubType.SUBMITTER && subAndApp.getOther() == 1) {
return new SubmitterAndApplicantExcutor(loanMapper);
}
if (subAndApp.getType()==SubAndApp.SubType.SUBMITTER && subAndApp.getOther() == 2) {
return new SubmitterAndAuditorExcutor(loanMapper);
}
if (subAndApp.getType()==SubAndApp.SubType.SUBMITTER && subAndApp.getOther() == 3) {
return new SubmitterAndPrinterExcutor(loanMapper);
}
if (subAndApp.getType()==SubAndApp.SubType.AUDITOR){
return new OnlyAuditorExcutor(loanMapper);
}
if (subAndApp.getType()==SubAndApp.SubType.APPROVER){
return new OnlyApproverExcutor(loanMapper);
}
return null;
}
}
使用工厂模式,将判断移到了工厂类中,在service层中只用调用工厂类中的生产方法,生产一个子类即可,便于维护,新增一个状态就新写一个子类,然后在工厂类中新增一个判断即可。
问题总结:
在优化过程中遇到了一个抽象类中无法注入Mapper的问题,抽象类不能生成实例对象,所以spring无法注入。解决方案是在service层中Autowired Mapper,然后在调用工厂类中的方法的时候把Mapper当成参数传入,然后在子类的添加一个带参的构造方法即可。