org.apache.commons.lang3.StringUtils这可是个好东西啊
在日常编写程序经常有类似的情况,正常情况下空字符串是不为空的,但是为了满足业务需求,空字符串也是不允许的。
这种情况怎么办?验证是不是很麻烦,我目前没有头绪,但是用StringUtils下的方法就能完美解决。
下面是面向接口编程中的一段代码:
用StringUtils的isnotblank方法检验type是否符合业务要求
public ServiceResponse<String> checkVaild(String str,String type){
//这里用到了StringUtils的isnotblank的特点,就是为空的字符串也是false,对于isnotempty空的字符串就不是空,是true
if(org.apache.commons.lang3.StringUtils.isNotBlank(type)){
//开始校验,点开上面的源码即可查看
if(Const.USERNAME.equals(type)){
int resultCount = userMapper.checkUsername(str);
if(resultCount>0){
return ServiceResponse.CreateByErrorMessage("用户名已存在!");
}
}
if(Const.EMAIL.equals(type)){
int resultCount=userMapper.checkEmail(str);
if(resultCount>0){
return ServiceResponse.CreateByErrorMessage("email已存在!");
}
}
}else{
return ServiceResponse.CreateByErrorMessage("参数错误");
}
return ServiceResponse.CreateBySuccessMessage("校验成功");
}
/**
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
*
* <pre>
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
* StringUtils.isBlank(" ") = true
* StringUtils.isBlank("bob") = false
* StringUtils.isBlank(" bob ") = false
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is null, empty or whitespace
* @since 2.0
* @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
*/
public static boolean isBlank(final CharSequence cs) {
int strLen;
if (cs == null || (strLen = cs.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (Character.isWhitespace(cs.charAt(i)) == false) {
return false;
}
}
return true;
}
/**
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
*
* <pre>
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
* StringUtils.isNotBlank(" ") = false
* StringUtils.isNotBlank("bob") = true
* StringUtils.isNotBlank(" bob ") = true
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is
* not empty and not null and not whitespace
* @since 2.0
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
*/
public static boolean isNotBlank(final CharSequence cs) {
return !isBlank(cs);
}
isempty和isnotempty同样很巧妙,感觉以后离不开她了
// Empty checks
//-----------------------------------------------------------------------
/**
* <p>Checks if a CharSequence is empty ("") or null.</p>
*
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
* StringUtils.isEmpty(" ") = false
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence.
* That functionality is available in isBlank().</p>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is empty or null
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
*/
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
/**
* <p>Checks if a CharSequence is not empty ("") and not null.</p>
*
* <pre>
* StringUtils.isNotEmpty(null) = false
* StringUtils.isNotEmpty("") = false
* StringUtils.isNotEmpty(" ") = true
* StringUtils.isNotEmpty("bob") = true
* StringUtils.isNotEmpty(" bob ") = true
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is not empty and not null
* @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
*/
public static boolean isNotEmpty(final CharSequence cs) {
return !isEmpty(cs);
}
if(org.apache.commons.lang3.StringUtils.equals(forgetToken,token)){
String md5password = MD5Util.MD5EncodeUtf8(passwordNew);
int rowCount = userMapper.updataPasswordByUsername(username,md5password);
if(rowCount>0){
return ServiceResponse.CreateBySuccessMessage("修改密码成功!");
}
}
* <pre>
* StringUtils.equals(null, null) = true
* StringUtils.equals(null, "abc") = false
* StringUtils.equals("abc", null) = false
* StringUtils.equals("abc", "abc") = true
* StringUtils.equals("abc", "ABC") = false
* </pre>
*
* @see Object#equals(Object)
* @param cs1 the first CharSequence, may be {@code null}
* @param cs2 the second CharSequence, may be {@code null}
* @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
* @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
*/
public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
if (cs1 == cs2) {
return true;
}
if (cs1 == null || cs2 == null) {
return false;
}
if (cs1.length() != cs2.length()) {
return false;
}
if (cs1 instanceof String && cs2 instanceof String) {
return cs1.equals(cs2);
}
return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, cs1.length());
}
下面介绍UUID的用法,在java.util.UUID下,上代码:
public static void main(String[] args) {
String forgottoken = UUID.randomUUID().toString();
System.out.println(forgottoken);
}
生成结果:
918489c5-a520-46b7-9380-d91ac93a59b5
通过上面的方法生成的一串唯一标示,叫宇宙最强无敌且不可重复。
还未短信找回密码,等一系列唯一标示身份验证而头疼吗?你值得拥有!
以邮箱找回密码为例,获得唯一标示之后如何是客户端与服务端产生联系呢?
我原来的想发是在回话过程漂浮一个session,发邮件时产生,定时回收。当然,用户登陆,唯一标示一直用session漂浮,登出是回收session没问题。但是像这种找回密码的唯一标示,用session会不会有点“昂贵”。毕竟就相当于安全级别高一点的验证码,session的话也容易被捕获。
所以使用本地缓存
LoadingCache http://www.jianshu.com/p/f4b99b70bd76
设置了本地缓存的清楚机制
新建了一个本地缓存的实体类:TokenCatch
package com.mmal.common;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2017/9/17.
*/
public class TokenCatch {
private static Logger logger = LoggerFactory.getLogger(TokenCatch.class);
public static final String TOKEN_PREFIX="token_";
//URL算法
private static LoadingCache<String,String> localCache = CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(10000).expireAfterAccess(12, TimeUnit.HOURS)
.build(new CacheLoader<String, String>() {
//默认的数据加载实现,当调用get取值的时候,如果key没有对应的值,就用这个方法实现。
@Override
public String load(String s) throws Exception {
return "null";
}
});
public static void setKey(String key,String value){
localCache.put(key,value);
}
public static String getKey(String key){
String value = null;
try {
value = localCache.get(key);
if("null".equals(value)){
return null;
}
return value;
}catch (Exception e){
logger.error("localcatch get error",e);
}
return null;
}
}
完成后,就可以像session一样的使用它了,毕竟上面的实体类自定义了getKey,和setKey俩个静态方法
public ServiceResponse<String> checkAnswer(String username,String question,String answer){
int resultCount=userMapper.checkAnswer(username,question,answer);
if(resultCount>0){
//说明问题和答案是这个用户的,且是正确的
String forgetToken = UUID.randomUUID().toString();
TokenCatch.setKey(TokenCatch.TOKEN_PREFIX+username,forgetToken);
return ServiceResponse.CreateBySuccess(forgetToken);
}
return ServiceResponse.CreateByErrorMessage("问题的答案错误!");
}
public ServiceResponse<String> forgetRestPassword(String username,String passwordNew,String forgetToken){
if(org.apache.commons.lang3.StringUtils.isBlank(forgetToken)){
return ServiceResponse.CreateByErrorMessage("校验错误,token需要被传递");
}
//这里直接复用的上面的内容
ServiceResponse validResponse =this.checkVaild(username,Const.USERNAME);
if(validResponse.isSucess()){
return ServiceResponse.CreateByErrorMessage("用户名不存在!");
}
String token = TokenCatch.getKey(TokenCatch.TOKEN_PREFIX+username);
if(org.apache.commons.lang3.StringUtils.isBlank(token)){
return ServiceResponse.CreateByErrorMessage("token无效或者过期");
}
//这个方法equals俩边都不为null,源码只要有一个为null,就位false
if(org.apache.commons.lang3.StringUtils.equals(forgetToken,token)){
String md5password = MD5Util.MD5EncodeUtf8(passwordNew);
int rowCount = userMapper.updataPasswordByUsername(username,md5password);
if(rowCount>0){
return ServiceResponse.CreateBySuccessMessage("修改密码成功!");
}
}else {
return ServiceResponse.CreateByErrorMessage("重置密码错误,请重新获取密码的token");
}
return ServiceResponse.CreateByErrorMessage("修改密码失败");
}