为了解决用户模块与业务模块的耦合,我想到用策略模式来来实现两套获取当前用户的方案。首先我要定义一个获取当前登陆用户的接口,如下:
package com.shangqiao56.tms;
import com.shangqiao56.User;
public interface UserHolder<T extends User> {
T getUser();
}
接着是一个controller的基类,并用getCurrentUser表示获取当前用户
public class TmsUserController{
@Autowired
private UserHolder<TmsUser> userHolder;
protected TmsUser getCurrentUser(){
return userHolder.getUser();
}
}
接着我添加一行配置。
shangqiao56:
user-holder: ##测试时配置的固定用户
type: fix # fix|default-sys-user
fix:
user-name: wangzhiping
user-id: 12
stat-id: 15
stat-name: 上海转运站
FixTmsUserHolder 表示从配置中读取一个静态用户。
public class FixTmsUserHolder implements UserHolder<TmsUser> {
@Value("${shangqiao56.user-holder.fix.user-id}")
private Long userId;
@Value("${shangqiao56.user-holder.fix.user-name}")
private String userName;
@Value("${shangqiao56.user-holder.fix.stat-id}")
private Long stationId;
@Value("${shangqiao56.user-holder.fix.stat-name}")
private String stationName;
public TmsUser getUser() {
TmsUser user = new TmsUser();
user.setId(userId);
user.setName(userName);
Station station = new Station();
station.setId(stationId);
station.setName(stationName);
user.setStation(station);
return user;
}
}
DefaultTmsUserHolder 表示正式环境中从网关获取用户信息。
public class DefaultTmsUserHolder implements UserHolder<TmsUser> {
private static final Logger log = LoggerFactory.getLogger(DefaultTmsUserHolder.class);
@Autowired
private HttpServletRequest request;
@Override
public TmsUser getUser() {
TmsUser tmsUser = new TmsUser();
Long userId = Long.parseLong(request.getHeader("x-user-id"));
Long statId = Long.parseLong(request.getHeader("x-station-id"));
String userName = getStringFromHeader("x-user-name");
String statName = getStringFromHeader("x-station-name");
Station station = new Station();
station.setId(statId);
station.setName(statName);
tmsUser.setStation(station);
tmsUser.setName(userName);
tmsUser.setId(userId);
return tmsUser;
}
private String getStringFromHeader(String key){
try {
return URLDecoder.decode(request.getHeader(key),"utf-8");
} catch (UnsupportedEncodingException e) {
log.error("UnsupportedEncodingException :{}",e);
}
return "";//todo
}
}
剩下的就是如何动态选择UserHolder.
public class TmsUserHolderConfig {
@Bean
@ConditionalOnProperty(
name = {"shangqiao56.user-holder.type"},
havingValue = "fix"
)
public UserHolder<TmsUser> fixUserHolder(){
return new FixTmsUserHolder();
}
@Bean
@ConditionalOnProperty(
name = {"shangqiao56.user-holder.type"},
havingValue = "false",
matchIfMissing = true)
public UserHolder<TmsUser> defaultUserHolder(){
return new DefaultTmsUserHolder();
}
}
这里主要要启到选择作用的是ConditionalOnProperty注解。
为了让idea能自动提示,添加 META-INF/spring-configuration-metadata.json文件:
{
"groups":[
{
"sourceType": "com.shangqiao56.common.config.SysConfigurationProperty",
"name": "shangqiao56.user-holder.fix",
"type": "com.shangqiao56.common.config.SysConfigurationProperty"
}
],
"properties":[
{
"name":"shangqiao56.user-holder.fix.user-name"
},
{
"name":"shangqiao56.user-holder.fix.user-id"
},
{
"name":"shangqiao56.user-holder.type",
"description" : "指定获取用户的类型,开发环境可以指定为fix,生产环境可指定的default-sys-user,每个模块可以根据自己需求扩展,以方便开发"
}
]
}