springboot+vue3实现《个人小博客》(一)登陆注册(带验证码)

案例目录
《个人小博客》
1、登录注册(带验证码)
2、发布小文章(添加文章)
3、文章管理(删改查)

项目技术栈介绍
前端:vue3+elementplus
后端:springboot+mybatisplus
jdk:1.8以上
数据库:mysql

演示开始

前端部分

第一:前端部分(注册模块效果图)


实现代码也非常简单

html代码:来自register.vue
                <p class="title">欢迎注册柠檬博客平台</p>
                    <el-form ref="formRef" :rules="rules" :model="formLabelAlign" label-width="90px">
                        <el-form-item prop="username" label="用户名">
                            <el-input ref="username" prefix-icon="el-icon-user" v-model.trim="formLabelAlign.username"
                                placeholder="请输入用户名" type="text" tabindex="1" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item prop="nickname" label="昵称">
                            <el-input ref="nickname" prefix-icon="el-icon-user" v-model.trim="formLabelAlign.nickname"
                                placeholder="请输入昵称" type="text" tabindex="1" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item prop="type" label="用户类型">
                            <el-select v-model="formLabelAlign.type" class="m-2" placeholder="选择用户类别">
                                <el-option v-for="item in options" :key="item.value" :label="item.label"
                                    :value="item.value" />
                            </el-select>
                        </el-form-item>
                        <el-form-item prop="sex" label="性别">
                            <el-radio-group v-model="formLabelAlign.sex" class="ml-4" >
                                <el-radio  v-for="item in SEX"  :label="item.value" size="large">{{ item.label}}</el-radio>
                            </el-radio-group>
                        </el-form-item>
                        <el-form-item prop="password" label="密码">
                            <el-input ref="nepassword" prefix-icon="el-icon-lock" v-model.trim="formLabelAlign.password"
                                placeholder="请输入密码" type="text" tabindex="1" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item prop="nepassword" label="确认密码">
                            <el-input ref="usernepasswordname" prefix-icon="el-icon-lock" v-model.trim="formLabelAlign.nepassword"
                                placeholder="请输入密码" type="text" tabindex="1" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" style="width: 100%;"
                                @click.native.prevent="submitForm('formLabelAlign')"
                                @keyup.enter.native="submitForm('formLabelAlign')">注册</el-button>
                        </el-form-item>
                    </el-form>
js代码
const formRef = ref(null);
const submitForm = () => {
    formRef.value.validate(async valid => {
        if (valid) {
            var param = {
                userName: formLabelAlign.username,
                password: formLabelAlign.password,
                nickName:formLabelAlign.nickname,
                sex:formLabelAlign.sex,
                type:formLabelAlign.type
            };
            register(param).then(res => {
                if(res.retCode==1){  
                    router.push("/login");
                }else{  
                    ElMessage({
				                    message: res.msg,
				                    type: 'error',
				          })
                }
          
            });
        } else {
            return false;
        }
    });
};
document.onkeydown = function (e) {
    if (window.event == undefined) {
        var key = e.keyCode;
    } else {
        var key = window.event.keyCode;
    }
    if (key == 13) {
        submitForm();
    }
};

第二:前端部分(登陆模块效果图)

html代码:来自login.html
<el-form ref="formRef" :rules="rules" :model="formLabelAlign"  label-width="70px">
            <el-form-item prop="username" label="用户名">
              <el-input
                ref="username"
                prefix-icon="el-icon-user"
                v-model.trim="formLabelAlign.username"
                placeholder="请输入用户名"
                type="text"
                tabindex="1"
                autocomplete="off"
              ></el-input>
            </el-form-item>
            <el-form-item prop="password"  label="密码">
              <el-input
                ref="username"
                prefix-icon="el-icon-lock"
                v-model.trim="formLabelAlign.password"
                placeholder="请输入密码"
                type="text"
                tabindex="1"
                autocomplete="off"
              ></el-input>
            </el-form-item>
            <el-form-item prop="urVerifiCode"  label="验证码" class="itemcode">
			  <el-input
			    ref="username"
			    prefix-icon="el-icon-lock"
			    v-model.trim="formLabelAlign.urVerifiCode"
			    placeholder="验证码"
			    type="text"
			    tabindex="1"
				style="width:100px;height: 40px;border-radius:none"
			    autocomplete="off"
			  ></el-input>
			  <span class="icodes" @click="getIcodes">
			    <!--<img class="img" :src="this.newcodeurl+'busineCommon/users/get/imagecode?uuid='+this.uid" alt="" style="width:120px;height: 40px" />-->
			    <img class="img" :src="imgurl" alt="" style="width:120px;height: 40px" />
			  </span>
			
			</el-form-item>
            <el-form-item>
              <el-button
                type="primary"
                style="width: 100%;"
                @click.native.prevent="submitForm('formLabelAlign')"
                @keyup.enter.native="submitForm('formLabelAlign')"
              >登录</el-button>
            </el-form-item>

            <el-form-item>
              <el-button
                type="danger"
                style="width: 100%;"
                @click="RegIster"
              
              >注册</el-button>
            </el-form-item>
          </el-form>
js代码:
const formLabelAlign = reactive({
  username: "",
  password: "",
  urVerifiCode:''
});
**注意配置接口**
const getcodes=()=>{
  getcode({}).then(res=>{
    imgurl.value = window.URL.createObjectURL(res);
  })
}
const getIcodes=()=>{
  getcodes();
}
const submitForm = () => {
  formRef.value.validate(async valid => {
    if (valid) {
      var param = {
        userName: formLabelAlign.username,
        password: formLabelAlign.password,
        code:formLabelAlign.urVerifiCode

      };
      login(param).then(res => {
        if(res.retCode==1){
           var token = res.data.token;
           var name = formLabelAlign.username;
           var url=res.avatar;
            res.data.userName=name;
            store.commit("SET_USER", res.data);
            store.commit("SET_TOKENS", token);
        }else{ 
          getcodes();
          ElMessage({
				      message: res.msg,
				      type: 'error',
				})
        }
      });
    } else {
      return false;
    }
  });
};
后端部分
开发步骤
  • 数据库建表 user_info
  • 项目搭建
  • 配置跨域
  • mybatisPlus配置
  • 编写user_info的增删改查
  • 配置swagger(接口文档)
  • 编写验证码接口
  • 编写注册接口
  • 编写登陆接口
  • 编写注销接口
  • 添加正则校验
  • 登陆过期过滤器

数据库建表

创建user_info表,其中主键为id,设为自增。其中登陆账号user_name,登陆密码password,昵称nick_name,人员类型type以及公有字段createTime和updateTime不可为空。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `user_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '登陆用户名',
  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '登录密码',
  `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '昵称',
  `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '邮箱',
  `img_id` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT '头像图片id',
  `type` int(11) NOT NULL DEFAULT 1 COMMENT '人员类型 1-普通用户,2-管理员',
  `sex` int(11) NOT NULL DEFAULT 0 COMMENT '性别 0-未知,1-男,2-女',
  `phone_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '手机号',
  `create_time` datetime(0) NOT NULL COMMENT '创建时间',
  `update_time` datetime(0) NOT NULL COMMENT '修改时间',
  `is_delete` int(11) NULL DEFAULT 0 COMMENT '是否删除 0-未删除,1-已删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

项目搭建

创建maven项目,随后在pom中引入Springboot、myabatisPlus、swagger、redis以及数据库连接池等依赖

pom.xml

<!--springboot-starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--springboot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!--springboot-redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        
        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version> 2.9.2</version>
        </dependency>

        <!--swagger-ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        
        <!--mysql连接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--mybatisPlus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatisPlus.version}</version>
        </dependency>
        
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

在项目中加入两个需要用到的公用分页实体类

PageRequest.java

@Data
@ApiModel("分页请求参数")
public class PageRequest<T> implements Serializable {

    //当前页(默认第一页)
    @ApiModelProperty(value = "当前页码,不传默认为1")
    private Integer pageNum = 1;

    //每页大小(默认每页20条)
    @ApiModelProperty(value = "每页条数,不传默认为20")
    private Integer pageSize = 20;

    //排序字段和方式
    private List<Sort> sortBy;

    //查询的数据
    @ApiModelProperty(value = "查询的参数")
    private T data;

    @Data
    public static class Sort{

        private String sortFiled;

        private String sort;
    }


}

PageResult.java

@Data
@ApiModel("分页结果")
public class PageResult<T> {

    //总条数
    @ApiModelProperty(value = "结果总条数")
    private Long total = 0L;

    //总页数
    @ApiModelProperty(value = "结果总页数")
    private Integer totalPage;

    //当前页数据
    @ApiModelProperty(value = "当前页的数据集")
    private List<T> data;

    //当前页
    @ApiModelProperty(value = "当前页")
    private Integer pageNum;

    //每页条数
    @ApiModelProperty(value = "每页条数")
    private Integer pageSize;

    //是否为最后页
    @ApiModelProperty(value = "是否为最后页")
    private Boolean isLastPage = false;

}

application.properties中需要加入mysql等配置

#端口号
server.port=8081

#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://xxxx:3306/xxxx?serverTimezone=GMT%2B8
useUnicode=true&characterEncoding=utf8
spring.datasource.username=xxxx
spring.datasource.password=xxxxx


配置跨域

因本系统采用前后端分离的方式开发,所以在后台需要配置请求跨域
WebConfig.java

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

    //跨域配置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOrigins("*")
                // 是否允许cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*");
    }
}

添加mybatisPlus的配置

application.properties

#指定mapper中xml文件的位置
mybatis-plus.mapper-locations  = classpath*:mapper/xml/*.xml

#mybatis中pojo的位置
mybatis-plus.type-aliases-package  = com.demo.model

#mybatis的主键策略
mybatis-plus.global-config.db-config.id-type =auto

mybatis-plus.global-config.db-config.logic-delete-field=isDelete

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

因为项目中有createTime和updateTime字段,在一些添加和修改的接口中,为了避免每次都需要给这两个字段赋值,所以可以通过实现MetaObjectHandler后,重写其中的insertFill和updateFill方法,这样在每次有添加和修改的请求调用时,都会走入这个方法中对这两个字段进行赋值。在使用时后面需要在实体类中对这两个字段进行配置。

FillFieldConfiguration.java

@Component
public class FillFieldConfiguration implements MetaObjectHandler {
        public FillFieldConfiguration() {
        }

        @Override
        public void insertFill(MetaObject metaObject) {
            Date date = new Date();
            String[] setterNames = metaObject.getSetterNames();
            for (String setterName : setterNames) {
                if(setterName.equals("createTime") && getFieldValByName("createTime",metaObject) == null){
                    metaObject.setValue("createTime", date);
                }
                if(setterName.equals("updateTime") && getFieldValByName("updateTime",metaObject) == null){
                    metaObject.setValue("updateTime", date);
                }
            }
        }

        @Override
        public void updateFill(MetaObject metaObject) {
            Date date = new Date();
            String[] setterNames = metaObject.getSetterNames();
            for (String setterName : setterNames) {
                if(setterName.equals("updateTime") && getFieldValByName("updateTime",metaObject) == null){
                    metaObject.setValue("updateTime", date);
                }
            }
        }
    }

user_info的增删改查

UserInfo.java

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("user_info")
@ApiModel(value="user_info对象", description="")
public class UserInfo{

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    @ApiModelProperty(value = "自增主键")
    private Integer id;

    @TableField("user_name")
    @ApiModelProperty(value = "登陆用户名")
    private String userName;

    @TableField("password")
    @ApiModelProperty(value = "登录密码")
    private String password;

    @TableField("nick_name")
    @ApiModelProperty(value = "昵称")
    private String nickName;

    @TableField("email")
    @ApiModelProperty(value = "邮箱")
    private String email;

    @TableField("img_id")
    @ApiModelProperty(value = "头像图片id")
    private String imgId;

    @TableField("type")
    @ApiModelProperty(value = "人员类型 1-普通用户,2-管理员")
    private Integer type;

    @TableField("sex")
    @ApiModelProperty(value = "性别 0-未知,1-男,2-女")
    private Integer sex;

    @TableField("phone_number")
    @ApiModelProperty(value = "手机号")
    private String phoneNumber;

    @TableField(value = "create_time",fill= FieldFill.INSERT)
    @ApiModelProperty(value = "创建时间")
    private Date createTime;

    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty(value = "修改时间")
    private Date updateTime;

    @TableField("is_delete")
    @ApiModelProperty(value = "是否删除 0-未删除,1-已删除")
    private Integer isDelete;

}

创建vo和dto

UserInfoQueryDTO.java

@Getter
@Setter
public class UserInfoQueryDTO {

	@ApiModelProperty("自增主键")
	private Integer id;

	@ApiModelProperty("登陆用户名")
	private String userName;

	@ApiModelProperty("登录密码")
	private String password;

	@ApiModelProperty("昵称")
	private String nickName;

	@ApiModelProperty("邮箱")
	private String email;

	@ApiModelProperty("头像图片id")
	private String imgId;

	@ApiModelProperty("人员类型 1-普通用户,2-管理员")
	private Integer type;

	@ApiModelProperty("性别 0-未知,1-男,2-女")
	private Integer sex;

	@ApiModelProperty("手机号")
	private String phoneNumber;

	@ApiModelProperty("创建时间")
	private Date createTime;

	@ApiModelProperty("修改时间")
	private Date updateTime;

	@ApiModelProperty("是否删除 0-未删除,1-已删除")
	private Integer isDelete;

}

UserInfoVO.java

@Getter
@Setter
public class UserInfoVO {

    @ApiModelProperty("自增主键")
    private Integer id;

    @ApiModelProperty("登陆用户名")
    private String userName;

    @ApiModelProperty("登录密码")
    private String password;

    @ApiModelProperty("昵称")
    private String nickName;

    @ApiModelProperty("邮箱")
    private String email;

    @ApiModelProperty("头像图片id")
    private String imgId;

    @ApiModelProperty("人员类型 1-普通用户,2-管理员")
    private Integer type;

    @ApiModelProperty("性别 0-未知,1-男,2-女")
    private Integer sex;

    @ApiModelProperty("手机号")
    private String phoneNumber;

    @ApiModelProperty("创建时间")
    private Date createTime;

    @ApiModelProperty("修改时间")
    private Date updateTime;

    @ApiModelProperty("是否删除 0-未删除,1-已删除")
    private Integer isDelete;

}

UserInfoController.java

@RestController
@Api(tags = {""})
@RequestMapping("/userInfo")
@CrossOrigin(allowCredentials = "true")
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;

    @RequestMapping(value = "/queryPageList", method = RequestMethod.POST)
    @ApiOperation("获取分页列表")
    public ResultData<PageResult<UserInfoVO>> queryPageList(@RequestBody PageRequest<UserInfoQueryDTO> pageRequest) {
        ResultData<PageResult<UserInfoVO>> pageResult = userInfoService.queryPageList(pageRequest);
        return pageResult;
    }

    @RequestMapping(value = "/queryList", method = RequestMethod.POST)
    @ApiOperation("获取列表")
    public ResultData<List<UserInfoVO>> queryList(@RequestBody UserInfoQueryDTO dto) {
        ResultData<List<UserInfoVO>> listResult = userInfoService.queryList(dto);
        return listResult;
    }

    @RequestMapping(value = "/queryDetail", method = RequestMethod.POST)
    @ApiOperation("获取详情")
    public ResultData<UserInfoVO> queryDetail(@RequestParam String id) {
        ResultData<UserInfoVO> detailResult = userInfoService.queryDetail(id);
        return detailResult;
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ApiOperation("新增")
    public ResultData<String> add(@RequestBody @Valid UserInfoInsertDTO dto, BindingResult bindingResult) throws IOException {
        if(bindingResult.hasErrors()){
            return ResultData.error(bindingResult.getFieldError().getDefaultMessage());
        }
        return userInfoService.add(dto);
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ApiOperation("编辑")
    public ResultData<String> edit(@RequestBody UserInfoUpdateDTO dto) {
        return userInfoService.edit(dto);
    }

    @RequestMapping(value = "/deleteById", method = RequestMethod.POST)
    @ApiOperation("删除")
    public ResultData<String> deleteById(@RequestParam String id) {
        return userInfoService.deleteById(id);
    }

    @RequestMapping(value = "/batchDeleteByIds", method = RequestMethod.POST)
    @ApiOperation("批量删除")
    public ResultData<String> batchDeleteByIds(@RequestParam List<String> ids) {
        return userInfoService.batchDeleteByIds(ids);
    }
}

UserInfoService.java

public interface UserInfoService {

	// 获取分页列表
	ResultData<PageResult<UserInfoVO>> queryPageList(PageRequest<UserInfoQueryDTO> pageRequest);

	// 获取列表
	ResultData<List<UserInfoVO>> queryList(UserInfoQueryDTO dto);

	// 获取详情
	ResultData<UserInfoVO> queryDetail(String id);

	// 新增
	ResultData<String> add(UserInfoInsertDTO dto);

	// 编辑
	ResultData<String> edit(UserInfoUpdateDTO dto);

	// 根据id删除
	ResultData<String> deleteById(String id);

	// 批量根据id删除
	ResultData<String> batchDeleteByIds(List<String> ids);

	// 批量根据条件删除
	ResultData<String> batchDelete(UserInfoDeleteDTO dto);

}

UserInfoServiceImpl.java

@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Override
    public ResultData<PageResult<UserInfoVO>> queryPageList(PageRequest<UserInfoQueryDTO> pageRequest) {
        Page<UserInfo> page = PageUtil.getPage(pageRequest);
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(BeanUtils.copyProperties(pageRequest.getData(), UserInfo.class));

        IPage<UserInfoVO> resultDate = this.page(page, queryWrapper)
        .convert(userInfo -> BeanUtils.copyProperties(userInfo, UserInfoVO.class));

        PageResult<UserInfoVO> pageResult = PageUtil.getPageResult(resultDate);
        return ResultData.success("查询成功", pageResult);
    }

    @Override
    public ResultData<List<UserInfoVO>> queryList(UserInfoQueryDTO dto) {
        UserInfo userInfo = BeanUtils.copyProperties(dto, UserInfo.class);
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(userInfo);
        List<UserInfo> userInfoList = this.list(queryWrapper);
        return ResultData.success("查询成功",BeanUtils.copyProperties(userInfoList, UserInfoVO.class));
    }

    @Override
    public ResultData<UserInfoVO> queryDetail(String id) {
        if(StringUtils.isBlank(id)){
            return ResultData.error("传入参数为空!");
        }
        return ResultData.success("查询成功",BeanUtils.copyProperties(this.getById(id), UserInfoVO.class));
    }

    @Override
    public ResultData<String> add(UserInfoInsertDTO dto) {
        Boolean result = this.save(BeanUtils.copyProperties(dto,UserInfo.class));
        if (!result) {
            return ResultData.error("添加失败!");
        }
        return ResultData.success("添加成功!");
    }

    @Override
    public ResultData<String> edit(UserInfoUpdateDTO dto) {
        if(dto.getId() == null){
            return ResultData.error("传入id不可为空!");
        }
        Boolean result = this.updateById(BeanUtils.copyProperties(dto,UserInfo.class));
        if (!result) {
            return ResultData.error("修改失败!");
        }
        return ResultData.success("修改成功!");
    }

    @Override
    public ResultData<String> deleteById(String id) {
        if(StringUtils.isBlank(id)){
            return ResultData.error("传入参数为空!");
        }
        Boolean result = this.removeById(id);
        if(!result){
            return ResultData.error("删除失败!");
        }
        return ResultData.success("删除成功!");
    }

    @Override
    public ResultData<String> batchDeleteByIds(List<String> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return ResultData.error("传入参数为空!");
        }
        int result = userInfoMapper.deleteBatchIds(ids);
        return ResultData.success("删除成功!删除了"+result+"条数据");
    }

    @Override
    public ResultData<String> batchDelete(UserInfoDeleteDTO dto) {
        UserInfo userInfo = BeanUtils.copyProperties(dto, UserInfo.class);
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(userInfo);
        int result = userInfoMapper.delete(queryWrapper);
        return ResultData.success("删除成功!删除了"+result+"条数据");
    }
}

UserInfoMapper.java

@Repository
public interface UserInfoMapper extends BaseMapper<UserInfo> {

}

配置swagger

SwaggerConfig.java

@Configuration
@EnableSwagger2           //开启swagger2
public class SwaggerConfig {
    //配置了swagger的Docket的bean实例

    @Value("${controller-locations}")
    private String url;


    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .ignoredParameterTypes(HttpSession.class, HttpServletRequest.class, HttpServletResponse.class)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(url))
                .paths(PathSelectors.any())
                .build();
    }
    //配置swagger信息
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("XX的swagger文档")
                .description("")
                .build();

    }
}

编写验证码接口

LoginController.java

@RestController
@CrossOrigin(allowCredentials = "true")
public class LoginController {

    @Autowired
    private RedisUtil redisUtil;
    
 /**
     * 得到登陆验证码
     * @author libing
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "getCode", method = RequestMethod.POST)
    public void getCode(HttpServletResponse response) throws IOException {

        //定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(116, 36, 4, 5);
        redisUtil.setEx(lineCaptcha.getCode(),lineCaptcha.getCode(),10, TimeUnit.MINUTES);
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            lineCaptcha.write(outputStream);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
 }   

注册接口

RegisterController.java

@RestController
@CrossOrigin(allowCredentials = "true")
public class RegisterController {

    @Autowired
    private UserInfoService userInfoService;


    @RequestMapping(value = "register", method = RequestMethod.POST)
    @ApiOperation("注册")
    public ResultData<String> register(@RequestBody @Valid RegisterDTO registerDTO, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return ResultData.error(bindingResult.getFieldError().getDefaultMessage());
        }

        UserInfoQueryDTO userInfoQueryDTO = new UserInfoQueryDTO();
        userInfoQueryDTO.setUserName(registerDTO.getUserName());
        ResultData<List<UserInfoVO>> listResultData = userInfoService.queryList(userInfoQueryDTO);
        if(!CollectionUtils.isEmpty(listResultData.getData())){
            return ResultData.error("您已注册过,不能重复注册!");
        }

        UserInfoInsertDTO userInfoInsertDTO = BeanUtils.copyProperties(registerDTO, UserInfoInsertDTO.class);
        ResultData<String> add = userInfoService.add(userInfoInsertDTO);
        if(add.isFail()){
            return ResultData.error(add.getMsg());
        }

        return ResultData.success("注册成功!");

    }
}

登陆接口

LoginController.java

@RestController
@CrossOrigin(allowCredentials = "true")
public class LoginController {

    @Autowired
    private UserInfoService userInfoService;


    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ApiOperation("登陆")
    public ResultData<LoginVO> login(@RequestBody @Valid LoginDTO loginDTO, BindingResult bindingResult, HttpServletRequest request,HttpServletResponse response ){

        if(bindingResult.hasErrors()){
            return ResultData.error(bindingResult.getFieldError().getDefaultMessage());
        }
        String code = redisUtil.get(loginDTO.getCode());
        if(StringUtils.isBlank(code)){
            return ResultData.error("验证码不正确!");
        }

        //查询用户
        UserInfoQueryDTO userInfoQueryDTO = new UserInfoQueryDTO();
        userInfoQueryDTO.setUserName(loginDTO.getUserName());
        ResultData<List<UserInfoVO>> listResultData = userInfoService.queryList(userInfoQueryDTO);
        if(CollectionUtils.isEmpty(listResultData.getData())){
            return ResultData.error("您尚未注册!");
        }

        List<UserInfoVO> data = listResultData.getData();
        if(data.size()>1){
            return ResultData.error("登陆不合法!");
        }

        UserInfoVO userInfoVO = data.get(0);
        if (!loginDTO.getPassword().equals(userInfoVO.getPassword())) {
            return ResultData.error("密码不正确!");
        }

        LoginVO loginVO = BeanUtils.copyProperties(userInfoVO, LoginVO.class);

        String token = JwtUtil.createJWT(String.valueOf(loginVO.getId()));

        redisUtil.setEx("login"+loginVO.getId(), JSON.toJSONString(loginVO),60,TimeUnit.MINUTES);
        response.setHeader("token",token);
        return ResultData.success("登陆成功",loginVO);
    }
}    

注销登录

LoginController.java

@RequestMapping(value = "unLogin", method = RequestMethod.POST)
    @ApiOperation("注销登陆")
    public ResultData<String> login(@RequestParam String id){
        if(StringUtils.isBlank(id)){
            return ResultData.error("用户id不能为空!");
        }
        redisUtil.delete("login"+id);
        return ResultData.success("注销成功!");
    }

添加正则校验

在注册时需要给电话号码,邮箱等字段进行合法性校验,所以需要加入正则校验

RegexUtils.java

/**
 * 正则工具类
 * @author zkx
 *
 */
public class RegexUtils {

	 /**
     * 验证Email
     * @param email email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkEmail(String email) {
        String regex = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
        return Pattern.matches(regex, email);
    }

    /**
     * 验证身份证号码
     * @param idCard 居民身份证号码18位,第一位不能为0,最后一位可能是数字或字母,中间16位为数字 \d同[0-9]
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkIdCard(String idCard) {
        String regex = "[1-9]\\d{16}[a-zA-Z0-9]{1}";
        return Pattern.matches(regex,idCard);
    }

    /**
     * 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
     * @param mobile 移动、联通、电信运营商的号码段
     *<p>移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
     *、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)</p>
     *<p>联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)</p>
     *<p>电信的号段:133、153、180(未启用)、189</p>
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkMobile(String mobile) {
        String regex = "(\\+\\d+)?1[3456789]\\d{9}$";
        return Pattern.matches(regex,mobile);
    }

    /**
     * 验证固定电话号码
     * @param phone 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
     * <p><b>国家(地区) 代码 :</b>标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9 的一位或多位数字,
     *  数字之后是空格分隔的国家(地区)代码。</p>
     * <p><b>区号(城市代码):</b>这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
     * 对不使用地区或城市代码的国家(地区),则省略该组件。</p>
     * <p><b>电话号码:</b>这包含从 0 到 9 的一个或多个数字 </p>
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkPhone(String phone) {
        String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
        return Pattern.matches(regex, phone);
    }
}    

在register接口中加入校验
RegisterController.java

if(StringUtils.isNotBlank(registerDTO.getPhoneNumber())){
            if(!RegexUtils.checkMobile(registerDTO.getPhoneNumber())){
                return ResultData.error("您输入的手机号码格式不正确!");
            }
        }

        if(StringUtils.isNotBlank(registerDTO.getEmail())){
            if(!RegexUtils.checkEmail(registerDTO.getEmail())){
                return ResultData.error("您输入的邮箱格式不正确!");
            }
        }


登陆过期过滤器

TokenInterceptor.java

@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private RedisUtil redisUtil;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        if(StringUtils.isNotBlank(token)){
            //解析token
            String userId;
            try {
                Claims claims = JwtUtil.parseJWT(token);
                userId = claims.getSubject();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("token非法");
            }
            //从redis中获取用户信息
            String json = redisUtil.get("login" + userId);
            if(StringUtils.isNotBlank(json)){
                return true;
            }
        }

        ResultData<Object> outTime = ResultData.outTime("身份验证失败");
        response.getOutputStream().write(JSON.toJSONString(outTime).getBytes());
        return false;
    }


}

源码获取地址(以上前后端代码已经全部打包好了)

https://gitee.com/xuxiaofei1996/case-source-code.git

为了方便大家更好的学习,本平台经常分享一些完整的单个功能案例代码给大家去练习,如果本平台没有你要学习的功能案例,你可以联系小编,提供你的小需求给我,我安排我们这边的开发团队免费帮你完成你的案例。

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

累人猿-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值