{
"token": "客户端token",
/**客户端构建版本号*/
"version": 11,
/**客户端平台类型*/
"platform": "IOS",
/**客户端设备型号*/
"machineModel": "Iphone 6s",
"imei": "客户端串号(手机)",
/**真正的消息体,应为map*/
"body": {
"key1": "value1",
"key2": {
"key21": "value21"
},
"key3": [
1,
]
}
}
{
/**是否成功*/
"success": false,
/**每个请求都会返回token,客户端每次请求都应使用最新的token*/
"token": "服务器为当前请求选择的token",
/**失败码*/
"failCode": 1,
/**业务消息或者失败消息*/
"msg": "未知原因",
/**返回的真实业务数据,可为任意可序列化的对象*/
"body": null
}
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
String requestBodyStr = webRequest.getParameter(requestBodyParamName);//获取请求报文,可以使用任意方式传递报文,只要在这获取到就可以
if(StringUtils.isNotBlank(requestBodyStr)){
String paramName = parameter.getParameterName();//获取Controller中参数名
Class<?> paramClass = parameter.getParameterType();//获取Controller中参数类型
/* 通过json工具类解析报文 */
JsonNode jsonNode = objectMapper.readTree(requestBodyStr);
if(paramClass.equals(ServiceRequest.class)){//ServiceRequest为请求报文对应的VO
ServiceRequest serviceRequest = objectMapper.readValue(jsonNode.traverse(),ServiceRequest.class);
return serviceRequest;//返回这个object就是注入到参数中了,一定要对应类型,否则异常不容易捕获
}
if(jsonNode!=null){//从报文中查找Controller中需要的参数
JsonNode paramJsonNode = jsonNode.findValue(paramName);
if(paramJsonNode!=null){
return objectMapper.readValue(paramJsonNode.traverse(), paramClass);
}
}
}
return null;
}
<mvc:argument-resolvers>
<!-- 统一的请求信息处理,从ServiceRequest中取数据 -->
<bean id="requestBodyResolver" class="com.niuxz.resolver.RequestBodyResolver">
<property name="objectMapper"><bean class="com.shoujinwang.utils.json.ObjectMapper"></bean></property>
<!-- 配置请求中ServiceRequest对应的字段名,默认为requestBody -->
<property name="requestBodyParamName"><value>requestBody</value></property>
</bean>
</mvc:argument-resolvers>
Matcher m1 =Pattern.compile("\"token\":\"(.*?)\"").matcher(requestBodyStr);
if(m1.find()){
token = m1.group(1);
}
tokenMapPool.verifyToken(token);//对token做公共处理,验证
<!-- 缓存管理器 全局变量等可以用它存取-->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg>
<ref bean="redisTemplate"/>
</constructor-arg>
<property name="usePrefix" value="true" />
<property name="cachePrefix">
<bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">
<constructor-arg name="delimiter" value=":@WebServiceInterface"/>
</bean>
</property>
<property name="expires"><!-- 缓存有效期 -->
<map>
<entry>
<key><value>tokenPoolCache</value></key><!-- tokenPool缓存名 -->
<value>2592000</value><!-- 有效时间 -->
</entry>
</map>
</property>
</bean>
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
/**
*
* 类 名: TokenMapPoolBean
* 描 述: token以及相关信息调用处理类
* 修 改 记 录:
* @version V1.0
* @date 2016年4月22日
* @author NiuXZ
*
*/
public class TokenMapPoolBean {
private static final Log log = LogFactory.getLog(TokenMapPoolBean.class);
/** 当前请求对应的token*/
private ThreadLocal<String> currentToken;
private CacheManager cacheManager;
private String cacheName;
private TokenGenerator tokenGenerator;
public TokenMapPoolBean(CacheManager cacheManager, String cacheName, TokenGenerator tokenGenerator) {
this.cacheManager = cacheManager;
this.cacheName = cacheName;
this.tokenGenerator = tokenGenerator;
currentToken = new ThreadLocal<String>();
}
/**
* 如果token合法就返回token,不合法就创建一个新的token并返回,
* 将token放入ThreadLocal中 并初始化一个tokenMap
* @param token
* @return token
*/
public String verifyToken(String token) {
// log.info("校验Token:\""+token+"\"");
String verifyedToken = null;
if (tokenGenerator.checkTokenFormat(token)) {
// log.info("校验Token成功:\""+token+"\"");
verifyedToken = token;
}
else {
verifyedToken = newToken();
}
currentToken.set(verifyedToken);
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new RuntimeException("获取不到存放token的缓存池,chacheName:" + cacheName);
}
ValueWrapper value = cache.get(verifyedToken);
//token对应的值为空,就创建一个新的tokenMap放入缓存中
if (value == null || value.get() == null) {
verifyedToken = newToken();
currentToken.set(verifyedToken);
Map<String, Object> tokenMap = new HashMap<String, Object>();
cache.put(verifyedToken, tokenMap);
}
return verifyedToken;
}
/**
* 生成新的token
* @return token
*/
private String newToken() {
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new RuntimeException("获取不到存放token的缓存池,chacheName:" + cacheName);
}
String newToken = null;
int count = 0;
do {
count++;
newToken = tokenGenerator.generatorToken();
}
while (cache.get(newToken) != null);
// log.info("创建Token成功:\""+newToken+"\" 尝试生成:"+count+"次");
return newToken;
}
/**
* 获取当前请求的tokenMap中对应key的对象
* @param key
* @return 当前请求的tokenMap中对应key的属性,模拟session
*/
public Object getAttribute(String key) {
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new RuntimeException("获取不到存放token的缓存池,chacheName:" + cacheName);
}
ValueWrapper tokenMapWrapper = cache.get(currentToken.get());
Map<String, Object> tokenMap = null;
if (tokenMapWrapper != null) {
tokenMap = (Map<String, Object>) tokenMapWrapper.get();
}
if (tokenMap == null) {
verifyToken(currentToken.get());
tokenMapWrapper = cache.get(currentToken.get());
tokenMap = (Map<String, Object>) tokenMapWrapper.get();
}
return tokenMap.get(key);
}
/**
* 设置到当前请求的tokenMap中,模拟session<br>
* TODO:此种方式设置attribute有问题:<br>
* 1、可能在同一token并发的情况下执行cache.put(currentToken.get(),tokenMap);时,<br>
* tokenMap可能不是最新,会导致丢失数据。<br>
* 2、每次都put整个tokenMap,数据量太大,需要优化<br>
* @param key value
*/
public void setAttribute(String key, Object value) {
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new RuntimeException("获取不到存放token的缓存池,chacheName:" + cacheName);
}
ValueWrapper tokenMapWrapper = cache.get(currentToken.get());
Map<String, Object> tokenMap = null;
if (tokenMapWrapper != null) {
tokenMap = (Map<String, Object>) tokenMapWrapper.get();
}
if (tokenMap == null) {
verifyToken(currentToken.get());
tokenMapWrapper = cache.get(currentToken.get());
tokenMap = (Map<String, Object>) tokenMapWrapper.get();
}
log.info("TokenMap.put(key=" + key + ",value=" + value + ")");
tokenMap.put(key, value);
cache.put(currentToken.get(), tokenMap);
}
/**
* 获取当前线程绑定的用户token
* @return token
*/
public String getToken() {
if (currentToken.get() == null) {
//初始化一次token
verifyToken(null);
}
return currentToken.get();
}
/**
* 删除token以及tokenMap
* @param token
*/
public void removeTokenMap(String token) {
if (token == null) {
return;
}
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new RuntimeException("获取不到存放token的缓存池,chacheName:" + cacheName);
}
log.info("删除Token:token=" + token);
cache.evict(token);
}
public CacheManager getCacheManager() {
return cacheManager;
}
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public String getCacheName() {
return cacheName;
}
public void setCacheName(String cacheName) {
this.cacheName = cacheName;
}
public TokenGenerator getTokenGenerator() {
return tokenGenerator;
}
public void setTokenGenerator(TokenGenerator tokenGenerator) {
this.tokenGenerator = tokenGenerator;
}
public void clear() {
currentToken.remove();
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import com.niuxz.base.Constants;
/**
*
* 类 名: LoginManager
* 描 述: 登录管理器
* 修 改 记 录:
* @version V1.0
* @date 2016年7月19日
* @author NiuXZ
*
*/
public class LoginManager {
private static final Log log = LogFactory.getLog(LoginManager.class);
private CacheManager cacheManager;
private String cacheName;
private TokenMapPoolBean tokenMapPool;
public LoginManager(CacheManager cacheManager, String cacheName, TokenMapPoolBean tokenMapPool) {
this.cacheManager = cacheManager;
this.cacheName = cacheName;
this.tokenMapPool = tokenMapPool;
}
public void login(String userId) {
log.info("用户登录:userId=" + userId);
Cache cache = cacheManager.getCache(cacheName);
ValueWrapper valueWrapper = cache.get(userId);
String token = (String) (valueWrapper == null ? null : valueWrapper.get());
tokenMapPool.removeTokenMap(token);//退出之前登录记录
tokenMapPool.setAttribute(Constants.LOGGED_USER_ID, userId);
cache.put(userId, tokenMapPool.getToken());
}
public void logoutCurrent(String phoneTel) {
String curUserId = getCurrentUserId();
log.info("用户退出:userId=" + curUserId);
tokenMapPool.removeTokenMap(tokenMapPool.getToken());//退出登录
if (curUserId != null) {
Cache cache = cacheManager.getCache(cacheName);
cache.evict(curUserId);
cache.evict(phoneTel);
}
}
/**
* 获取当前用户的id
* @return
*/
public String getCurrentUserId() {
return (String) tokenMapPool.getAttribute(Constants.LOGGED_USER_ID);
}
public CacheManager getCacheManager() {
return cacheManager;
}
public String getCacheName() {
return cacheName;
}
public TokenMapPoolBean getTokenMapPool() {
return tokenMapPool;
}
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public void setCacheName(String cacheName) {
this.cacheName = cacheName;
}
public void setTokenMapPool(TokenMapPoolBean tokenMapPool) {
this.tokenMapPool = tokenMapPool;
}
}
public void sendValiCodeByPhoneNum(String phoneNum, String hintMsg, String logSuffix) {
validatePhoneTimeSpace();
// 获取6位随机数
String code = CodeUtil.getValidateCode();
log.info(code + "------->" + phoneNum);
// 调用短信验证码下发接口
RetStatus retStatus = msgSendUtils.sendSms(code + hintMsg, phoneNum);
if (!retStatus.getIsOk()) {
log.info(retStatus.toString());
throw new ThrowsToDataException(ServiceResponseCode.FAIL_INVALID_PARAMS, "手机验证码获取失败,请稍后再试");
}
// 重置session
tokenMapPool.setAttribute(Constants.VALIDATE_PHONE, phoneNum);
tokenMapPool.setAttribute(Constants.VALIDATE_PHONE_CODE, code.toString());
tokenMapPool.setAttribute(Constants.SEND_CODE_WRONGNU, 0);
tokenMapPool.setAttribute(Constants.SEND_CODE_TIME, new Date().getTime());
log.info(logSuffix + phoneNum + "短信验证码:" + code);
}
@RequestMapping("record")
@ResponseBody
public ServiceResponse record(String message){
String userId = loginManager.getCurrentUserId();
messageBoardService.recordMessage(userId, message);
return ServiceResponseBuilder.buildSuccess(null);
}
import org.apache.commons.lang3.StringUtils;
import com.niuxz.base.pojo.ServiceResponse;
import com.niuxz.utils.spring.SpringContextUtil;
import com.niuxz.web.server.token.TokenMapPoolBean;
/**
*
* 类 名: ServiceResponseBuilder
*
* @version V1.0
* @date 2016年4月25日
* @author NiuXZ
*
*/
public class ServiceResponseBuilder {
/**
* 构建一个成功的响应信息
*
* @param body
* @return 一个操作成功的 ServiceResponse
*/
public static ServiceResponse buildSuccess(Object body) {
return new ServiceResponse(
((TokenMapPoolBean) SpringContextUtil.getBean("tokenMapPool"))
.getToken(),
"操作成功", body);
}
/**
* 构建一个成功的响应信息
*
* @param body
* @return 一个操作成功的 ServiceResponse
*/
public static ServiceResponse buildSuccess(String token, Object body) {
return new ServiceResponse(token, "操作成功", body);
}
/**
* 构建一个失败的响应信息
*
* @param failCode
* msg
* @return 一个操作失败的 ServiceResponse
*/
public static ServiceResponse buildFail(int failCode, String msg) {
return buildFail(failCode, msg, null);
}
/**
* 构建一个失败的响应信息
*
* @param failCode
* msg body
* @return 一个操作失败的 ServiceResponse
*/
public static ServiceResponse buildFail(int failCode, String msg,
Object body) {
return new ServiceResponse(
((TokenMapPoolBean) SpringContextUtil.getBean("tokenMapPool"))
.getToken(),
failCode, StringUtils.isNotBlank(msg) ? msg : "操作失败", body);
}
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有