The project requirements

When the latest development of the system rights management system, there is such a requirement that different roles have different data rights, which need to be processed according to the scope of data, and have different departments’ data viewing rights, such as this

if(all) {get all department ids}else if(Local level) {Current user department ID}else if(Principal and child) {current user department and child department IDS}else{custom department IDS}Copy the code

Currently only 4 layers, although this is easy to understand, logical clear, but although the expansion of the system,if… Too many else’s. That’s a scary one. So use the policy pattern to eliminate if else.

Policy pattern is a decoupled method, which encapsulates the algorithm and separates the algorithm invocation from the algorithm itself. With policy mode, client code does not need to be tweaked, and algorithms can be replaced with each other because different algorithms implement the same interface. Optimize the above code to:

@Autowired private DataScopeContext dataScopeContext; Ids List<Integer> IDS = dataScopeContext.getDeptIdsForDataScope(roleDto, roleDto.getDsType());Copy the code

When users select different data ranges, the context is used to judge the selection of resources to call the resource pool, and the same getDeptIdsForDataScope method is used to select and process different logic according to different types, so as to achieve structural optimization. The specific logic is:

  • Define a policy handler interface, and then each policy class implements this handler interface and the processing logic.
  • Then a Strategy definition context is determined, and all implementation classes that implement Strategy are automatically injected into strategyMap class through Spring, and corresponding strategies are obtained according to type
Code display:

Policy interface AbstractDataScopeHandler class

/** * @class name AbstractDataScopeHandler * @description Created by Lihaodong (alias[email protected] * @date 2019-06-08 15:45 * @version 1.0 */ public interface AbstractDataScopeHandler  @param roleDto * @param dataScopeTypeEnum * @return
     */
    List<Integer> getDeptIds(RoleDTO roleDto, DataScopeTypeEnum dataScopeTypeEnum);
}
Copy the code

The policy class implements this policy interface (only one is presented)

package com.xd.pre.strategy; import com.xd.pre.constant.DataScopeTypeEnum; import com.xd.pre.domain.SysDept; import com.xd.pre.dto.RoleDTO; import com.xd.pre.service.ISysDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; /** * @classname AllDataScope * @description * @author Created by Lihaodong (alias[email protected] * @date 2019-06-08 16:27 * @version 1.0 */ @component ("1") public class AllDataScope implements AbstractDataScopeHandler { @Autowired private ISysDeptService deptService; Override public List<Integer> getDeptIds(RoleDTO RoleDTO, DataScopeTypeEnum dataScopeTypeEnum) { List<SysDept> sysDepts = deptService.list();returnsysDepts.stream().map(SysDept::getDeptId).collect(Collectors.toList()); }}Copy the code

Service injects a policy set and obtains the corresponding policy based on type

package com.xd.pre.strategy; import com.xd.pre.constant.DataScopeTypeEnum; import com.xd.pre.dto.RoleDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @classname DataScopeContext * @description Create an environment role Context: * @author Created by Lihaodong (alias[email protected] * @date 2019-06-08 16:11 * @version 1.0 */ @service public class DataScopeContext { @Autowired private final Map<String, AbstractDataScopeHandler> strategyMap = new ConcurrentHashMap<>(); /** * the 1 in Component specifies its name, @param strategyMap */ public DataScopeContext(Map<String, AbstractDataScopeHandler> strategyMap) { strategyMap.forEach(this.strategyMap::put); } public List<Integer> getDeptIdsForDataScope(RoleDTO roleDto, Integertype) {
        return strategyMap.get(String.valueOf(type)).getDeptIds(roleDto, DataScopeTypeEnum.valueOf(type)); }}Copy the code

The service layer calls the getDeptIdsForDataScope method

From this, you can see that different resources can be obtained automatically by fetching different department ids in different types.

The advantage of using the policy pattern is that it can freely switch between different algorithms through an encapsulated context, eliminating multiple judgments, and has good scalability.

When there are too many strategies, it will appear bloated. I suggest you to use the design mode reasonably and refer to my open source project for understanding.

Gitee.com/li_haodong/…