完成登录且优化:
未优化做简单的判断:
全部异常抓捕
优化:返回的是json的格式
BusinessException:所有的错误放到这个容器中,全局异常从这个类中调用
BusinessException:
package com.lya.lyaspshop.exception; import com.lya.lyaspshop.resp.JsonResponseStatus; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true)//自动生成equals和hashCode方法 @AllArgsConstructor//自动生成全参构造函数 @NoArgsConstructor//自动生成无参构造函数 @Data//自动生成getters、setters、toString public class BusinessException extends RuntimeException { // 所有的错误放到这个容器中,全局异常从这个类中调用 private JsonResponseStatus jsonResponseStatus; }
GlobalExceptionHandler
package com.lya.lyaspshop.exception; import com.lya.lyaspshop.resp.JsonResponseBody; import com.lya.lyaspshop.resp.JsonResponseStatus; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice//用于声明这个类是一个全局异常处理器 @Slf4j public class GlobalExceptionHandler { // 已知错误 @ExceptionHandler(BusinessException.class)//声明这是一个异常处理方法 public JsonResponseBody<?> exceptionBusinessException(BusinessException e) { JsonResponseStatus status = e.getJsonResponseStatus(); log.info(status.getMsg());//使用日志打印异常的消息。 return JsonResponseBody.other(status); } // 未知错误 @ExceptionHandler(Throwable.class) public JsonResponseBody<?> exceptionThrowable(Throwable e) { log.info(e.getMessage());//使用日志打印异常的消息。 return JsonResponseBody.other(JsonResponseStatus.UN_KNOWN); } }
这里为啥要写这两个类:
理解:编写
GlobalExceptionHandler
类可以集中处理应用程序中的各种异常,提高代码的可维护性,同时简化了代码
jsr303
//这里体现了为啥要建这个类:1.降低代码耦合度:VO 实体类可以将数据从数据库实体类中解耦 2.用户进行权限校验等操作,业务逻辑与数据访问层分离开来,提高代码的可读性和可维护性 如果我直接在数据库的实体类中去
<!-- jsr303 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
实体:使用注解
@NotBlank
抛一个异常:
报错信息:
这个是时候错误已经该变:
连接日志查看:
遇到一个问题:这里就是异常就是使用的303自己带的异常,不要写其他的
前后台的加密过程:
从前台发送请求来:
引入加密js
<script src="http://www.gongjuji.net/Content/files/jquery.md5.js" type="text/javascript"></script>
加密成功:
加密后数据库的原密码肯定是不对的了。这我们使用debug给截取到密码存入数据库中。
集成redis
<!-- redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
RedisServiceImpl
package com.lya.lyaspshop.service.impl; import com.lya.lyaspshop.pojo.User; import com.lya.lyaspshop.service.IRedisService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class RedisServiceImpl implements IRedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; // 往redis设置 @Override public void setUserToRedis(String token, User user) { redisTemplate.opsForValue().set("user:" + token, user, 7200, TimeUnit.SECONDS); } @Override public User getUserByToken(String token) { return (User) redisTemplate.opsForValue().get("user:" + token); } }
IRedisService
package com.lya.lyaspshop.service; import com.lya.lyaspshop.pojo.User; public interface IRedisService { /** * 将登陆User对象保存到Redis中,并以Token为键 */ void setUserToRedis(String token, User user); /** * 根据token令牌获取redis中存储的user对象 */ User getUserByToken(String token); }
redisService.setUserToRedis(token, one);
加入cookie
使用CookieUtils类:
package com.lya.lyaspshop.utils; import lombok.extern.slf4j.Slf4j; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; @Slf4j public class CookieUtils { /** * @Description: 得到Cookie的值, 不编码 */ public static String getCookieValue(HttpServletRequest request, String cookieName) { return getCookieValue(request, cookieName, false); } /** * @Description: 得到Cookie的值 */ public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) { Cookie[] cookieList = request.getCookies(); if (cookieList == null || cookieName == null) { return null; } String retValue = null; try { for (int i = 0; i < cookieList.length; i++) { if (cookieList[i].getName().equals(cookieName)) { if (isDecoder) { retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8"); } else { retValue = cookieList[i].getValue(); } break; } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return retValue; } /** * @Description: 得到Cookie的值 */ public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) { Cookie[] cookieList = request.getCookies(); if (cookieList == null || cookieName == null) { return null; } String retValue = null; try { for (int i = 0; i < cookieList.length; i++) { if (cookieList[i].getName().equals(cookieName)) { retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString); break; } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return retValue; } /** * @Description: 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) { setCookie(request, response, cookieName, cookieValue, -1); } /** * @param request * @param response * @param cookieName * @param cookieValue * @param cookieMaxage * @Description: 设置Cookie的值 在指定时间内生效,但不编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) { setCookie(request, response, cookieName, cookieValue, cookieMaxage, false); } /** * @Description: 设置Cookie的值 不设置生效时间,但编码 * 在服务器被创建,返回给客户端,并且保存客户端 * 如果设置了SETMAXAGE(int seconds),会把cookie保存在客户端的硬盘中 * 如果没有设置,会默认把cookie保存在浏览器的内存中 * 一旦设置setPath():只能通过设置的路径才能获取到当前的cookie信息 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, boolean isEncode) { setCookie(request, response, cookieName, cookieValue, -1, isEncode); } /** * @Description: 设置Cookie的值 在指定时间内生效, 编码参数 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) { doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode); } /** * @Description: 设置Cookie的值 在指定时间内生效, 编码参数(指定编码) */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) { doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString); } /** * @Description: 删除Cookie带cookie域名 */ public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) { doSetCookie(request, response, cookieName, null, -1, false); } /** * @Description: 设置Cookie的值,并使其在指定时间内生效 */ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) { try { if (cookieValue == null) { cookieValue = ""; } else if (isEncode) { cookieValue = URLEncoder.encode(cookieValue, "utf-8"); } Cookie cookie = new Cookie(cookieName, cookieValue); if (cookieMaxage > 0) cookie.setMaxAge(cookieMaxage); if (null != request) {// 设置域名的cookie String domainName = getDomainName(request); log.info("========== domainName: {} ==========", domainName); if (!"localhost".equals(domainName)) { cookie.setDomain(domainName); } } cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { e.printStackTrace(); } } /** * @Description: 设置Cookie的值,并使其在指定时间内生效 */ private static void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) { try { if (cookieValue == null) { cookieValue = ""; } else { cookieValue = URLEncoder.encode(cookieValue, encodeString); } Cookie cookie = new Cookie(cookieName, cookieValue); if (cookieMaxage > 0) cookie.setMaxAge(cookieMaxage); if (null != request) {// 设置域名的cookie String domainName = getDomainName(request); log.info("========== domainName: {} ==========", domainName); if (!"localhost".equals(domainName)) { cookie.setDomain(domainName); } } cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { e.printStackTrace(); } } /** * @Description: 得到cookie的域名 */ private static String getDomainName(HttpServletRequest request) { String domainName = null; String serverName = request.getRequestURL().toString(); if (serverName == null || serverName.equals("")) { domainName = ""; } else { serverName = serverName.toLowerCase(); serverName = serverName.substring(7); final int end = serverName.indexOf("/"); serverName = serverName.substring(0, end); if (serverName.indexOf(":") > 0) { String[] ary = serverName.split("\\:"); serverName = ary[0]; } final String[] domains = serverName.split("\\."); int len = domains.length; if (len > 3 && !isIp(serverName)) { // www.xxx.com.cn domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1]; } else if (len <= 3 && len > 1) { // xxx.com or xxx.cn domainName = "." + domains[len - 2] + "." + domains[len - 1]; } else { domainName = serverName; } } return domainName; } public static String trimSpaces(String IP) {//去掉IP字符串前后所有的空格 while (IP.startsWith(" ")) { IP = IP.substring(1, IP.length()).trim(); } while (IP.endsWith(" ")) { IP = IP.substring(0, IP.length() - 1).trim(); } return IP; } public static boolean isIp(String IP) {//判断是否是一个IP boolean b = false; IP = trimSpaces(IP); if (IP.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) { String s[] = IP.split("\\."); if (Integer.parseInt(s[0]) < 255) if (Integer.parseInt(s[1]) < 255) if (Integer.parseInt(s[2]) < 255) if (Integer.parseInt(s[3]) < 255) b = true; } return b; } }
自定义注解
根据@isNoblank去写:
这三行代码必须写的:
boolean require() default false; String expr() default ""; String message() default "";
IsMobile
package com.lya.lyaspshop.core; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Documented @Constraint(validatedBy = {IsMobileConstraintValidator.class}) @Target({FIELD}) @Retention(RUNTIME) public @interface IsMobile { boolean require() default false; String expr() default ""; String message() default ""; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
IsMobileConstraintValidator
package com.lya.lyaspshop.core; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author CloudJun */ public class IsMobileConstraintValidator implements ConstraintValidator<IsMobile, String> { private boolean require; private String expr; @Override public void initialize(IsMobile isMobile) { expr = isMobile.expr(); require = isMobile.require(); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (!require) return true; if (StringUtils.isEmpty(value)) return false; return value.matches(expr); } }
优化:定义一个常量类(使用的定值往这里调用就行)
package com.lya.lyaspshop.core; public abstract class Constants { // 常类 public static final String EXPR_MOBILE = "(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}"; public static final String EXPR_PASSWORD = "[a-zA-Z0-9]{32}"; public static final String USER_TOKEN_PREFIX = "user:"; }