最近在第三方测试上浪费太多时间,主要想不间断获取实时数据,本以为完成不了没想到还真测试出来了。
接下来主要做对接第三方接口,可以用聚合接口,每天有免费次数,也可以使用新浪接口或者东方接口,最近在测试新浪和东方的接口上发现,新浪行情使用的websocket方式进行数据推送,对接下来接受的数据无法乱码目前没有解决方案。在新浪上面浪费太多时间,最终也没解决,
然后又试了试东方,东方使用的长连接推送数据,这个测试下来是可以获取行情并且因为长连接所以也是可以实时获取数据
先创建用户实体
@PostMapping(value = "/addUser")
@ApiOperation(value = "新建用户接口")
public ApiRespResult addUser(@Valid AuthorityUser user) {
ApiRespResult result = null;
try {
AuthorityUser loginUser = getUser();
// 用户登陆处理
authorityUserService.addUser(user, loginUser);
result = ApiRespResult.success();
}catch(ComponentException e) {
log.error(e.getMessage(), e);
result = ApiRespResult.error(e.getErrorCodeEnum());
}catch(Exception e) {
log.error(e.getMessage(), e);
result = ApiRespResult.sysError(e.getMessage());
}
return result;
}
@PostMapping(value = "/login")
@ApiOperation(value = "用户登陆接口")
@ApiImplicitParams({
@ApiImplicitParam(value = "用户账号", name = "userAccount", dataType = "string", required = true),
@ApiImplicitParam(value = "用户密码", name = "password", dataType = "string", required = true)
})
public ApiRespResult login(@Size(min = 1, max = 32,message = "账号长度必须为1到32")
@RequestParam("userAccount") String userAccount,
@Size(min = 1, max = 32,message = "密码长度必须为1到32")
@RequestParam("password")String password) {
ApiRespResult result = null;
try {
// 用户登陆处理
AuthorityUser authorityUser = authorityUserService.userLogin(userAccount, password, getClientIP());
// 保存用户登陆信息至session
getSession().setAttribute(getSession().getId(), authorityUser);
result = ApiRespResult.success();
}catch(Exception e) {
log.error(e.getMessage(), e);
result = ApiRespResult.sysError(e.getMessage());
}
return result;
}
微服务群会存在多个节点,如果采用随机的负载策略, 那如何确保用户的会话数据不会丢失?
这里我们通过Spring Session Redis技术方案, 基于统一缓存方式, 实现分布式会话管理。
pom.xml添加
org.springframework.session
spring-session-data-redis
配置项添加
# Spring 分布式session
spring:
session:
store-type: redis
增加注解:
在启动类中添加
@EnableRedisHttpSession
public class StockAdminUserApplication {
...
}
项目使用:
把以上配置好, 就和我们正常使用session一样, 这里把一些常用的session操作作了封装,
放在BaseController里面:
public class BaseController {
/**
* 根据账号获取用户对象
* @return
*/
protected AuthorityUser getUser() throws ComponentException {
HttpSession session = getSession();
AuthorityUser authorityUser = (AuthorityUser)session.getAttribute(session.getId());
if(null == authorityUser) {
// 用户不存在, 抛出异常
throw new ComponentException(ApplicationErrorCodeEnum.ADMIN_USER_NEED_LOGIN);
}
return authorityUser;
}
/**
* 获取session会话
* @return
*/
protected HttpSession getSession() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest().getSession();
}
...
}
@Override
public AuthorityUser userLogin(String userAccount, String password, String clientIp) throws ComponentException {
//查找用户
Optional authorityUserOptional = authorityUserRepository.findOne(eqUserName(userAccount));
if(!authorityUserOptional.isPresent()){
throw new ComponentException(ApplicationErrorCodeEnum.ADMIN_USER_ACCOUNT_EXISTS);
}
//用户校验
AuthorityUser authorityUser = authorityUserOptional.get();
String encryptPassword = EncryptUtil.encryptSigned(password);
if(!authorityUser.getUserPassword().equals(encryptPassword)){
throw new ComponentException(ApplicationErrorCodeEnum.ADMIN_USER_ACCOUNT_PWD_ERROR);
}
//记录用户登录信息
authorityUser.setLastLoginTime(new Date());
authorityUser.setLastLoginIp(clientIp);
authorityUserRepository.save(authorityUser);
//用户的角色权限,并且拿最大角色权限
List roleList = authorityUserRoleRepository.findAllByUserId(authorityUser.getId());
if(roleList==null || roleList.size()==0){
throw new ComponentException(ApplicationErrorCodeEnum.ADMIN_USER_NOT_ASSIGN_ROLES);
}
Long roleId = getPriortyAuthorityUserRole(roleList).getRoleId();
authorityUser.setRoleId(roleId);
//获取用户的角色菜单操作信息,存入缓存中
List optList = authorityMenuOperationRepository.findByRoleId(roleId);
if(null != optList) {
// 根据接口的请求类型, 做分组汇总处理, 转换为MAP结构, 格式: POST-{/add, /update}
Map> optUrlSets = optList.stream().collect(Collectors.groupingBy(AuthorityMenuOperation::getOperationIco,
Collectors.mapping(AuthorityMenuOperation::getOperationUri, Collectors.toSet())));
if(optUrlSets.size() > 0) {
// 将MAP的菜单操作信息存入至Redis缓存当中, 格式: key=userId + | + optType, value=Set...
Cache cache = cacheManager.getCache(GlobalConstants.AUTHORITY_MENU_KEY);
optUrlSets.forEach((opt, urls) -> {
// 对uri集合做遍历处理, 将权限菜单信息按指定格式存入至Redis当中
// 注意: set里面的数据, 是可以支持多个uri记录, 需拆分处理转换至Set集合当中
Set levelUrls = urls.stream().flatMap(str ->
Arrays.stream(str.split(",")).map(String::trim)).collect(Collectors.toSet());
cache.put(authorityUser.getId() + GlobalConstants.SPLIT + opt, levelUrls);
});
}
}
return authorityUser;
}
用户登陆接口看似简单, 但里面还是要处理较多逻辑, 来分析下:
其余接口就不一一整理了。
后台用户管理系统, 涉及众多菜单与操作, 并不是每个用户都可以请求访问, 而是根据用户角色访问相应其对应的菜单, 这就需要通过全局拦截器来作校验判断。
理解专业生产级行情服务的整体功能设计
掌握PostgreSQL的安装与配置(服务器目前有用,暂时还继续使用mysql存储)
留言与评论(共有 0 条评论) “” |