zoukankan      html  css  js  c++  java
  • 代码优化设计(一)

    1、通用的结果处理,及错误信息类封装

    2、md5前台后台两次加盐加密

    3、全局异常处理

    4、通用的key生成策略

    5、通用的RedisService方法

    通用的结果处理,及错误信息类封装

    写一个Result类来封装返回结果,避免重复性的代码出现到controller层

    package com.javaxl.miaosha_02.result;
    
    public class Result<T> {
        
        private int code;
        private String msg;
        private T data;
        
        /**
         *  成功时候的调用
         * */
        public static  <T> Result<T> success(T data){
            return new Result<T>(data);
        }
        
        /**
         *  失败时候的调用
         * */
        public static  <T> Result<T> error(CodeMsg codeMsg){
            return new Result<T>(codeMsg);
        }
        
        private Result(T data) {
            this.data = data;
        }
        
        private Result(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
        
        private Result(CodeMsg codeMsg) {
            if(codeMsg != null) {
                this.code = codeMsg.getCode();
                this.msg = codeMsg.getMsg();
            }
        }
        
        
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
        public T getData() {
            return data;
        }
        public void setData(T data) {
            this.data = data;
        }
    }

    CodeMsg:对系统常量进行封装

    package com.javaxl.miaosha_02.result;
    
    public class CodeMsg {
        
        private int code;
        private String msg;
        
        //通用的错误码
        public static CodeMsg SUCCESS = new CodeMsg(0, "success");
        public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务端异常");
        public static CodeMsg BIND_ERROR = new CodeMsg(500101, "参数校验异常:%s");
        //登录模块 5002XX
        public static CodeMsg SESSION_ERROR = new CodeMsg(500210, "Session不存在或者已经失效");
        public static CodeMsg PASSWORD_EMPTY = new CodeMsg(500211, "登录密码不能为空");
        public static CodeMsg MOBILE_EMPTY = new CodeMsg(500212, "手机号不能为空");
        public static CodeMsg MOBILE_ERROR = new CodeMsg(500213, "手机号格式错误");
        public static CodeMsg MOBILE_NOT_EXIST = new CodeMsg(500214, "手机号不存在");
        public static CodeMsg PASSWORD_ERROR = new CodeMsg(500215, "密码错误");
        
        
        //商品模块 5003XX
        
        
        //订单模块 5004XX
        public static CodeMsg ORDER_NOT_EXIST = new CodeMsg(500400, "订单不存在");
        
        //秒杀模块 5005XX
        public static CodeMsg MIAO_SHA_OVER = new CodeMsg(500500, "商品已经秒杀完毕");
        public static CodeMsg REPEATE_MIAOSHA = new CodeMsg(500501, "不能重复秒杀");
        
        
        private CodeMsg( ) {
        }
                
        private CodeMsg( int code,String msg ) {
            this.code = code;
            this.msg = msg;
        }
        
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
        
        public CodeMsg fillArgs(Object... args) {
            int code = this.code;
            String message = String.format(this.msg, args);
            return new CodeMsg(code, message);
        }
    
        @Override
        public String toString() {
            return "CodeMsg [code=" + code + ", msg=" + msg + "]";
        }
        
        
    }

    md5前台后台两次加盐加密
    一次:客户端密码加密,防止明文密码被劫持

    二次:服务端shiro再加密一次

    前台加密js代码:

    function doLogin(){
        g_showLoading();
        
        var inputPass = $("#password").val();
        var salt = g_passsword_salt;
        var str = ""+salt.charAt(0)+salt.charAt(2) + inputPass +salt.charAt(5) + salt.charAt(4);
        var password = md5(str);
        
        $.ajax({
            url: "/login/do_login",
            type: "POST",
            data:{
                mobile:$("#mobile").val(),
                password: password
            },
            success:function(data){
                layer.closeAll();
                if(data.code == 0){
                    layer.msg("成功");
                    window.location.href="/goods/to_list";
                }else{
                    layer.msg(data.msg);
                }
            },
            error:function(){
                layer.closeAll();
            }
        });
    }

    后台MiaoshaUserService : 

    package com.javaxl.miaosha_02.service;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletResponse;
    
    import com.javaxl.miaosha_02.dao.MiaoshaUserDao;
    import com.javaxl.miaosha_02.domain.MiaoshaUser;
    import com.javaxl.miaosha_02.exception.GlobalException;
    import com.javaxl.miaosha_02.redis.MiaoshaUserKey;
    import com.javaxl.miaosha_02.redis.RedisService;
    import com.javaxl.miaosha_02.result.CodeMsg;
    import com.javaxl.miaosha_02.shiro.PasswordHelper;
    import com.javaxl.miaosha_02.util.MD5Util;
    import com.javaxl.miaosha_02.util.UUIDUtil;
    import com.javaxl.miaosha_02.vo.LoginVo;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class MiaoshaUserService {
        
        
        public static final String COOKI_NAME_TOKEN = "token";
        
        @Autowired
        MiaoshaUserDao miaoshaUserDao;
        
        @Autowired
        RedisService redisService;
        
        public MiaoshaUser getById(long id) {
            //取缓存
            MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
            if(user != null) {
                return user;
            }
            //取数据库
            user = miaoshaUserDao.getById(id);
            if(user != null) {
                redisService.set(MiaoshaUserKey.getById, ""+id, user);
            }
            return user;
        }
        // http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323
        public boolean updatePassword(String token, long id, String formPass) {
            //取user
            MiaoshaUser user = getById(id);
            if(user == null) {
                throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
            }
            //更新数据库
            MiaoshaUser toBeUpdate = new MiaoshaUser();
            toBeUpdate.setId(id);
            toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
            miaoshaUserDao.update(toBeUpdate);
            //处理缓存
            redisService.delete(MiaoshaUserKey.getById, ""+id);
            user.setPassword(toBeUpdate.getPassword());
            redisService.set(MiaoshaUserKey.token, token, user);
            return true;
        }
    
    
        public MiaoshaUser getByToken(HttpServletResponse response, String token) {
            if(StringUtils.isEmpty(token)) {
                return null;
            }
            MiaoshaUser user = redisService.get(MiaoshaUserKey.token, token, MiaoshaUser.class);
            //延长有效期
            if(user != null) {
                addCookie(response, token, user);
            }
            return user;
        }
        
    
        public String login(HttpServletResponse response, LoginVo loginVo) {
            if(loginVo == null) {
                throw new GlobalException(CodeMsg.SERVER_ERROR);
            }
            String mobile = loginVo.getMobile();
            String formPass = loginVo.getPassword();
            //判断手机号是否存在
            MiaoshaUser user = getById(Long.parseLong(mobile));
            if(user == null) {
                throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
            }
            //验证密码
            String dbPass = user.getPassword();
            String saltDB = user.getSalt();
            if(!PasswordHelper.checkCredentials(formPass, saltDB, dbPass)) {
                throw new GlobalException(CodeMsg.PASSWORD_ERROR);
            }
            //生成cookie
            String token     = UUIDUtil.uuid();
            addCookie(response, token, user);
            return token;
        }
        
        private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
            redisService.set(MiaoshaUserKey.token, token, user);
            Cookie cookie = new Cookie(COOKI_NAME_TOKEN, token);
            cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
            cookie.setPath("/");
            response.addCookie(cookie);
        }
    
    }


    全局异常处理

    如果系统发生了异常,不做统一异常处理,前端会给用户展示一大片看不懂的文字。做统一异常处理后当异常发生后可以给用户一个温馨的提示,不至于使用户满头雾水,所以一方面是为了更好的用户体验 如果不统一全局异常,服务端和前端在遇到异常的时候处理起来杂乱无章非常费力。所以另一方面是为了制定规范提高工作效率
    我们都知道使用 try-catch 可以捕捉异常,可以 throws 抛出异常。那么在 Spring Boot 中我们如何处理异常,如何处理得更加优雅呢


    自定义异常类:

    package com.javaxl.miaosha_02.exception;
    
    
    import com.javaxl.miaosha_02.result.CodeMsg;
    
    public class GlobalException extends RuntimeException{
    
        private static final long serialVersionUID = 1L;
        
        private CodeMsg cm;
        
        public GlobalException(CodeMsg cm) {
            super(cm.toString());
            this.cm = cm;
        }
    
        public CodeMsg getCm() {
            return cm;
        }
    
    }

    全局异常处理类

    package com.javaxl.miaosha_02.exception;
    
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    
    import com.javaxl.miaosha_02.result.CodeMsg;
    import com.javaxl.miaosha_02.result.Result;
    import org.springframework.validation.BindException;
    import org.springframework.validation.ObjectError;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    
    @ControllerAdvice
    @ResponseBody
    public class GlobalExceptionHandler {
        @ExceptionHandler(value=Exception.class)
        public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
            e.printStackTrace();
            if(e instanceof GlobalException) {
                GlobalException ex = (GlobalException)e;
                return Result.error(ex.getCm());
            }else if(e instanceof BindException) {
                BindException ex = (BindException)e;
                List<ObjectError> errors = ex.getAllErrors();
                ObjectError error = errors.get(0);
                String msg = error.getDefaultMessage();
                return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
            }else {
                return Result.error(CodeMsg.SERVER_ERROR);
            }
        }
    }

    通用的key生成策略

    KeyPrefix
    package com.javaxl.miaosha_02.redis;
    
    public interface KeyPrefix {
    
    
        public int expireSeconds();//过期时间设置
        
        public String getPrefix();//前缀
        
    }
    BasePrefix :
    package com.javaxl.miaosha_02.redis;
    
    public abstract class BasePrefix implements KeyPrefix{
        
        private int expireSeconds;
        
        private String prefix;
        
        public BasePrefix(String prefix) {//0代表永不过期
            this(0, prefix);
        }
        
        public BasePrefix( int expireSeconds, String prefix) {
            this.expireSeconds = expireSeconds;
            this.prefix = prefix;
        }
        
        public int expireSeconds() {//默认0代表永不过期
            return expireSeconds;
        }
    
        public String getPrefix() {
            String className = getClass().getSimpleName();
            return className+":" + prefix;
        }
    
    }

    以MiaoshaUserKey为例
    package com.javaxl.miaosha_02.redis;
    
    public class MiaoshaUserKey extends BasePrefix{
    
        public static final int TOKEN_EXPIRE = 3600*24 * 2;
        private MiaoshaUserKey(int expireSeconds, String prefix) {
            super(expireSeconds, prefix);
        }
        public static MiaoshaUserKey token = new MiaoshaUserKey(TOKEN_EXPIRE, "tk");
        public static MiaoshaUserKey getById = new MiaoshaUserKey(0, "id");
    }

    通用的RedisService方法

    高并发redis做缓存是很通用的手段,避免出现重复的redis操作方法

    搞个通用的存值、取值、自增、自减...的方法

    package com.javaxl.miaosha_02.redis;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.alibaba.fastjson.JSON;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    
    @Service
    public class RedisService {
        
        @Autowired
        JedisPool jedisPool;
        
        /**
         * 获取当个对象
         * */
        public <T> T get(KeyPrefix prefix, String key,  Class<T> clazz) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                 //生成真正的key
                 String realKey  = prefix.getPrefix() + key;
                 String  str = jedis.get(realKey);
                 T t =  stringToBean(str, clazz);
                 return t;
             }finally {
                  returnToPool(jedis);
             }
        }
        
        /**
         * 设置对象
         * */
        public <T> boolean set(KeyPrefix prefix, String key,  T value) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                 String str = beanToString(value);
                 if(str == null || str.length() <= 0) {
                     return false;
                 }
                //生成真正的key
                 String realKey  = prefix.getPrefix() + key;
                 int seconds =  prefix.expireSeconds();
                 if(seconds <= 0) {
                     jedis.set(realKey, str);
                 }else {
                     jedis.setex(realKey, seconds, str);
                 }
                 return true;
             }finally {
                  returnToPool(jedis);
             }
        }
        
        /**
         * 判断key是否存在
         * */
        public <T> boolean exists(KeyPrefix prefix, String key) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                //生成真正的key
                 String realKey  = prefix.getPrefix() + key;
                return  jedis.exists(realKey);
             }finally {
                  returnToPool(jedis);
             }
        }
        
        /**
         * 删除
         * */
        public boolean delete(KeyPrefix prefix, String key) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                //生成真正的key
                String realKey  = prefix.getPrefix() + key;
                long ret =  jedis.del(key);
                return ret > 0;
             }finally {
                  returnToPool(jedis);
             }
        }
        
        /**
         * 增加值
         * */
        public <T> Long incr(KeyPrefix prefix, String key) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                //生成真正的key
                 String realKey  = prefix.getPrefix() + key;
                return  jedis.incr(realKey);
             }finally {
                  returnToPool(jedis);
             }
        }
        
        /**
         * 减少值
         * */
        public <T> Long decr(KeyPrefix prefix, String key) {
             Jedis jedis = null;
             try {
                 jedis =  jedisPool.getResource();
                //生成真正的key
                 String realKey  = prefix.getPrefix() + key;
                return  jedis.decr(realKey);
             }finally {
                  returnToPool(jedis);
             }
        }
        
        private <T> String beanToString(T value) {
            if(value == null) {
                return null;
            }
            Class<?> clazz = value.getClass();
            if(clazz == int.class || clazz == Integer.class) {
                 return ""+value;
            }else if(clazz == String.class) {
                 return (String)value;
            }else if(clazz == long.class || clazz == Long.class) {
                return ""+value;
            }else {
                return JSON.toJSONString(value);
            }
        }
    
        @SuppressWarnings("unchecked")
        private <T> T stringToBean(String str, Class<T> clazz) {
            if(str == null || str.length() <= 0 || clazz == null) {
                 return null;
            }
            if(clazz == int.class || clazz == Integer.class) {
                 return (T)Integer.valueOf(str);
            }else if(clazz == String.class) {
                 return (T)str;
            }else if(clazz == long.class || clazz == Long.class) {
                return  (T)Long.valueOf(str);
            }else {
                return JSON.toJavaObject(JSON.parseObject(str), clazz);
            }
        }
    
        private void returnToPool(Jedis jedis) {
             if(jedis != null) {
                 jedis.close();
             }
        }
    
    }
  • 相关阅读:
    Java第三季
    LeetCode(10)Regular Expression Matching
    LeetCode(9)Palindrome Number
    shell基础编程
    LeetCode(8)String to Integer (atoi)
    使用python绘制词云
    我的书单
    LeetCode(7)Reverse Integer
    获取新浪微博的Access_token
    c语言中,常见数据类型的字节数
  • 原文地址:https://www.cnblogs.com/psyu/p/12110945.html
Copyright © 2011-2022 走看看