- 一.项目搭建
- 二 编写测试类
- 三 编写数据库
- 四 编写工具类
- 五 导入静态资源
- 六 编写登录功能
- 七 引入303校验
1.新建一个SpringBoot项目
2.导入依赖
Spring Web
Lombok
mysql
Thymeleaf
MP # mybatis-plus需要去官网复制
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎,类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。
Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用
3.编辑配置文件 application.yml
spring:
#thymeleaf 配置
thymeleaf:
# 关闭缓存
cache: false
#配置数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///seckill?useUnicode=true&characterEncoding=utf-8&serverTimeZone=Asia/Shanghai
username: root
password: root
#配置连接池
hikari:
#连接池名字
pool-name: HikariPool
#最小空间连接数
minimum-idle: 5
#最大连接数,默认10,可以不设置
maximum-pool-size: 10
#连接最大存活时间,0表示永久,默认30分钟,可以不设置
max-lifetime: 1800000
#空闲连接存活最大时间,默认10分钟(600000ms),这里设置半个小时
idle-timeout: 1800000
#连接超时时间,默认30秒
connection-timeout: 30000
#心态机制,测试连接是否可用,如果有问题说明我们的连接池有问题
connection-test-query: select 1
#从连接池返回的连接自动提交
auto-commit: true
#Mybatis-plus配置
mybatis-plus:
#配置XXXMapper.xml的映射路径
mapper-locations: classpath*:/mapper
@Controller
@RequestMapping("/test")
public class TestController {
//测试页面跳转
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","老王");
return "hello";
}
}
2.在tenplates包下新建一个hello.html
测试
3.启动项目,测试看是否成功
输入controller的地址,就会跳转到页面
1.新建一个数据库,seckill,注意选择编码格式
2.建表
CREATE TABLE t_user( `id` BIGINT(20) NOT NULL COMMENT '用户ID,用手机号码代替', `nickname` VARCHAr(200) NOT NULL COMMENT '昵称', `password` VARCHAr(32) DEFAULT NULL COMMENT '前端传给后端先用md5加密(明文+固定的salt值),后端存数据库之前再加盐加密,双重加密', `slat` VARCHAr(10) DEFAULT NULL COMMENT '盐值', `head` VARCHAr(128) DEFAULT NULL COMMENT '头像', `register_date` datetime DEFAULT NULL COMMENT '注册时间', `last_login_date` datetime DEFAULT NULL COMMENT '最后一次登录时间', `login_count` INT(10) DEFAULT '0' COMMENT '登录次数', PRIMARY KEY(`id`) )四 编写工具类
1.需要用到md5加密,md5加密操作
2.编写各个包,这里需要添加一个vo包
- 1 创建LoginVo
package cn.bs.demoseckill.vo;
import com.sun.istack.internal.NotNull;
import lombok.Data;
//介绍账号密码
@Data
public class LoginVo {
@NotNull
//@IsMobile
private String mobile;
@NotNull
//@Length(min = 32)
private String password;
}
这里注释掉的东西后面我们在补回来
- 2 创建一个RespBean
package cn.bs.demoseckill.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespBean {
private long code;
private String message;
private Object obj;
//登录成功返回的消息
public static RespBean success(){
return new RespBean(RespBeanEnum.SUCCESS.getCODE(), RespBeanEnum.SUCCESS.getMESSAGE(), null);
}
public static RespBean success(Object obj){
return new RespBean(RespBeanEnum.SUCCESS.getCODE(), RespBeanEnum.SUCCESS.getMESSAGE(), obj);
}
//登录失败返回的消息
public static RespBean error(RespBeanEnum pe){
return new RespBean(pe.getCODE(), pe.getMESSAGE(), null);
}
public static RespBean error(RespBeanEnum pe, Object obj){
return new RespBean(pe.getCODE(), pe.getMESSAGE(), obj);
}
}
- 3 创建一个RespBeaEnum
package cn.bs.demoseckill.vo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
@AllArgsConstructor
@ToString
@Getter
public enum RespBeanEnum {
SUCCESS("成功",200),
ERROR("服务器异常",500),
LOGIN_ERROR("休想白嫖,请登录",530),
LOGIN_FAILED("账号或者密码不正确",531),
LOGIN_FAILEDP("密码不对",532);
private final String MESSAGE;
private final Integer CODE;
}
五 导入静态资源
- 分析login跳转
- 编写登录层
package cn.bs.seckill.controller;
import cn.bs.seckill.service.UserService;
import cn.bs.seckill.vo.LoginVo;
import cn.bs.seckill.vo.RespBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
//@RestController 返回的是类里面东西,Controller才是跳转到静态资源
@Slf4j
@RequestMapping("/login")
public class LoginController {
@Autowired
private UserService userService;
//跳转登录页面
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/doLogin")
@ResponseBody
public RespBean doLogin(LoginVo loginVo){
return userService.doLogin(loginVo);
}
}
@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径;用于方法上,表示在类的父路径下追加方法上注解中的地址将会访问到该方法 @RequestMapping 后,返回值通常解析为跳转路径,加上 *@Responsebody* 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中,一般在异步获取数据时使用【也就是AJAX】,所以你如果是ajax请求,请把它加上,不然报错你又瓜起
2.编写业务逻辑,先在UserService接口里面添加doLogin方法,然后去实现类实现
public interface UserService {
//登录接口
RespBean doLogin(LoginVo loginVo);
}
然后在实现类里写好我们的登录方法
@Service public class UserServiceImpl extends ServiceImplimplements UserService { @Autowired private UserMapper userMapper; @Override public RespBean doLogin(LoginVo loginVo) { String mobile = loginVo.getMobile(); String password = loginVo.getPassword(); //判断账号密码是否为空 if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)) { return RespBean.error(RespBeanEnum.LOGIN_ERROR); } //判断是否正确输入手机号 if (!ValidatorUtil.isMobile(mobile)){ return RespBean.error(RespBeanEnum.LOGIN_FAILED); } User user = userMapper.selectById(mobile); //判断手机号是否存在 if (null==user){ return RespBean.error(RespBeanEnum.LOGIN_FAILED); } //判断密码是否正确 if (!(user.getPassword()).equals(MD5Util.toDBPassEpt(password))){ return RespBean.error(RespBeanEnum.LOGIN_FAILEDP); } return RespBean.success(); } }
3.测试是否能登录
输入一个账号密码,我这里以123456为例子,把它做两次加密,j就是这个b7797cce01b4b131b433b6acf4add449,然后存入数据库中
数据库里id就是登录的账号
1.导入依赖
org.springframework.boot
spring-boot-starter-validation
我们为了判断用户是否输入了正确的账号格式编写了大量的代码,为了节省时间,我们可以用303数据校验
2.因为我的账号密码是通过传到后端是通过我们的LoginVo这个类里面的两个属性搞的,所以我们需要在这个类的两个属性上面加上判断注解
@Data
public class LoginVo {
@NotNull
@IsMobile
private String mobile;
@NotNull
@Length(min = 32)
private String password;
}
@IsMobile是我们自定义的注解,以后在开发当中,我们也可以仿照这种方式来自定义需要的注解
3.新建一个IsMobile注解,下面的代码不用自己写,可以通过进入@NotNull注解进入底层代码复制这一段,为什么需要自定义这个注解呢?因为我们需要判断手机号是否是必须输入的内容,而@NotNull做不到
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//校验规则
@Constraint(
validatedBy = {MobileValidator.class}
)
public @interface IsMobile {
//添加一个方法作为验证手机号为必填
boolean required() default true;
String message() default "{请输入正确的手机号}";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
4.@Constraint( validatedBy = {MobileValidator.class})这个方法里面的参数,是校验规则,所以我们需要新建一个类来负责编写校验规则
public class MobileValidator implements ConstraintValidator{ private boolean required = false; //初始化,因为是手机号,所以我们就判断是否为必填 @Override public void initialize(IsMobile constraintAnnotation) { //调用此方法,把required赋值为真 required = constraintAnnotation.required(); } @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { //如果是必填 if (required) { //判断手机号格式是否正确 return ValidatorUtil.isMobile(s); } //如果是非必填 else { //返回为真 if (StringUtils.isEmpty(s)) { return true; } else { //判断格式是否正确 return ValidatorUtil.isMobile(s); } } } }
其中initialize为初始化方法,可以在里面做一些初始化操作,isValid方法就是我们最终需要的校验方法了。可以在该方法中实现具体的校验步骤。
5.接下来把UserServiceImpl层里面的两个判断手机是否为空和格式是否正确的两段代码注释掉
@Service public class UserServiceImpl extends ServiceImplimplements UserService { @Autowired private UserMapper userMapper; @Override public RespBean doLogin(LoginVo loginVo) { String mobile = loginVo.getMobile(); String password = loginVo.getPassword(); User user = userMapper.selectById(mobile); //判断手机号是否存在 if (null==user){ return RespBean.error(RespBeanEnum.LOGIN_FAILED); } //判断密码是否正确 if (!(user.getPassword()).equals(MD5Util.toDBPassEpt(password))){ return RespBean.error(RespBeanEnum.LOGIN_FAILEDP); } return RespBean.success(); } }
6.在LoginController层的doLogin方法的参数里加上我们的注解
@Controller
//@RestController 返回的是类里面东西,Controller才是跳转到静态资源
@Slf4j
@RequestMapping("/login")
public class LoginController {
@Autowired
private UserService userService;
//跳转登录页面
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/doLogin")
//注意必须的有Resp这个注解,不然
@ResponseBody
public RespBean doLogin( @Valid LoginVo loginVo){
return userService.doLogin(loginVo);
}
}
7.开始测试,故意乱输手机号,后端就会收到异常



