SpringBoot2+Vue2实战(六)登录,注册实现及自定义异常处理,个人信息页面与昵称头像功能实现

news/2024/11/17 7:25:10/

一、登录:

UserDto


@Data
public class UserDto {private String username;private String password;@Alias("nickname")private String nickname;private String avatarUrl;
}

UserController

 //登录@PostMapping("/login")public Result login(@RequestBody UserDto userDto) {String username = userDto.getUsername();String password = userDto.getPassword();if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {return Result.error(Constants.CODE_400, "系统错误");}UserDto dto = userService.login(userDto);return success(dto);}

UserService


public interface UserService extends IService<User> {UserDto login(UserDto userDto);
}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Resourceprivate UserMapper userMapper;private static final Log LOG = Log.get();@Overridepublic UserDto login(UserDto userDto) {User one = getUserInfo(userDto);if (one != null){BeanUtil.copyProperties(one,userDto,true);return userDto;}else {throw new ServiceException(Constants.CODE_600,"用户名或密码错误");}}private User getUserInfo(UserDto userDto) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",userDto.getUsername());queryWrapper.eq("password",userDto.getPassword());User one;try{one = getOne(queryWrapper);}catch (Exception e){LOG.error(e);throw new ServiceException(Constants.CODE_500,"系统错误");}return one;}}

Login.vue 

<template><div class="wrapper"><div style="margin: 200px auto; background-color: #fff; width: 350px; height: 300px; padding: 20px; border-radius: 10px"><div style="margin: 20px 0; text-align: center; font-size: 24px"><b>登 录</b></div><el-form :model="user" :rules="rules" ref="userForm"><el-form-item prop="username"><el-input size="medium" style="margin: 10px 0" prefix-icon="el-icon-user" v-model="user.username"></el-input></el-form-item><el-form-item prop="password"><el-input size="medium" style="margin: 10px 0" prefix-icon="el-icon-lock" show-password v-model="user.password"></el-input></el-form-item><el-form-item style="margin: 10px 0; text-align: right"><el-button type="primary" size="small"  autocomplete="off" @click="login">登录</el-button><el-button type="warning" size="small"  autocomplete="off">注册</el-button></el-form-item></el-form></div></div>
</template><script>
export default {name: "Login",data() {return {user: {},rules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' },{ min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }],}}},methods: {login() {this.$refs['userForm'].validate((valid) => {if (valid) {  // 表单校验合法this.request.post("/user/login", this.user).then(res => {if (res.code === '200'){//存储用户信息到浏览器localStorage.setItem("user",JSON.stringify(res.data))this.$router.push("/")this.$message.success("登录成功")}else {this.$message.error(res.msg)}})}});}
}
</script><style>
.wrapper {height: 100vh;background-image: linear-gradient(to bottom right, #FC466B , #3F5EFB);overflow: hidden;
}
</style>

router/index.js

 {path: '/login',name: 'Login',component: () => import('../views/Login.vue')}

二、退出

Header.vue

<el-dropdown-item style="font-size: 14px; padding: 5px 0"><span style="text-decoration: none" @click="logout">退出</span></el-dropdown-item>data() {return {user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}}},methods: {logout() {this.$router.push("/login")localStorage.removeItem("user")this.$message.success("退出成功")}}

三、注册

router/index.js

{path: '/register',name: 'Register',component: () => import('../views/Register.vue')},

Header.vue

<template><div class="wrapper"><div style="margin: 100px auto; background-color: #fff; width: 350px; height: 400px; padding: 20px; border-radius: 10px"><div style="margin: 20px 0; text-align: center; font-size: 24px"><b>注 册</b></div><el-form :model="user" :rules="rules" ref="userForm"><el-form-item prop="username"><el-input placeholder="请输入账号" size="medium" style="margin: 5px 0" prefix-icon="el-icon-user" v-model="user.username"></el-input></el-form-item><el-form-item prop="password"><el-input placeholder="请输入密码" size="medium" style="margin: 5px 0" prefix-icon="el-icon-lock" show-password v-model="user.password"></el-input></el-form-item><el-form-item prop="confirmPassword"><el-input placeholder="请确认密码" size="medium" style="margin: 5px 0" prefix-icon="el-icon-lock" show-password v-model="user.confirmPassword"></el-input></el-form-item><el-form-item style="margin: 5px 0; text-align: right"><el-button type="primary" size="small"  autocomplete="off" @click="register">注册</el-button><el-button type="warning" size="small"  autocomplete="off" @click="$router.push('/login')">返回登录</el-button></el-form-item></el-form></div></div>
</template><script>
export default {name: "Register",data() {return {user: {},rules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' },{ min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }],confirmPassword: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }],}}},methods: {register() {this.$refs['userForm'].validate((valid) => {if (valid) {  // 表单校验合法if (this.user.password !== this.user.confirmPassword) {this.$message.error("两次输入的密码不一致")return false}this.request.post("/user/register", this.user).then(res => {if(res.code === '200') {this.$message.success("注册成功")this.$router.push("/login")} else {this.$message.error(res.msg)}})}});}}
}
</script><style>
.wrapper {height: 100vh;background-image: linear-gradient(to bottom right, #FC466B , #3F5EFB);overflow: hidden;
}
</style>

Login.vue

methods: {login() {this.$refs['userForm'].validate((valid) => {if (valid) {  // 表单校验合法this.request.post("/user/login", this.user).then(res => {if (res.code === '200'){//存储用户信息到浏览器localStorage.setItem("user",JSON.stringify(res.data))this.$router.push("/")this.$message.success("登录成功")}else {this.$message.error(res.msg)}})}});}}

Register.vue

<template><div class="wrapper"><div style="margin: 100px auto; background-color: #fff; width: 350px; height: 400px; padding: 20px; border-radius: 10px"><div style="margin: 20px 0; text-align: center; font-size: 24px"><b>注 册</b></div><el-form :model="user" :rules="rules" ref="userForm"><el-form-item prop="username"><el-input placeholder="请输入账号" size="medium" style="margin: 5px 0" prefix-icon="el-icon-user" v-model="user.username"></el-input></el-form-item><el-form-item prop="password"><el-input placeholder="请输入密码" size="medium" style="margin: 5px 0" prefix-icon="el-icon-lock" show-password v-model="user.password"></el-input></el-form-item><el-form-item prop="confirmPassword"><el-input placeholder="请确认密码" size="medium" style="margin: 5px 0" prefix-icon="el-icon-lock" show-password v-model="user.confirmPassword"></el-input></el-form-item><el-form-item style="margin: 5px 0; text-align: right"><el-button type="primary" size="small"  autocomplete="off" @click="register">注册</el-button><el-button type="warning" size="small"  autocomplete="off" @click="$router.push('/login')">返回登录</el-button></el-form-item></el-form></div></div>
</template><script>
export default {name: "Register",data() {return {user: {},rules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' },{ min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }],confirmPassword: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur' }],}}},methods: {register() {this.$refs['userForm'].validate((valid) => {if (valid) {  // 表单校验合法if (this.user.password !== this.user.confirmPassword) {this.$message.error("两次输入的密码不一致")return false}this.request.post("/user/register", this.user).then(res => {if(res.code === '200') {this.$message.success("注册成功")this.$router.push("/login")} else {this.$message.error(res.msg)}})}});}}
}
</script><style>
.wrapper {height: 100vh;background-image: linear-gradient(to bottom right, #FC466B , #3F5EFB);overflow: hidden;
}
</style>

router/index.js

{path: '/register',name: 'Register',component: () => import('../views/Register.vue')}

User.vue

methods: {load() {this.request.get("/user/selectPage", {params: {pageNum: this.pageNum,pageSize: this.pageSize,username: this.username,email: this.email,address: this.address,}}).then(res => {//注意datathis.tableData = res.data.recordsthis.total = res.data.total})},save() {this.request.post("/user/saveUser", this.form).then(res => {if (res.data) {this.$message.success("保存成功")this.dialogFormVisible = falsethis.load()} else {this.$message.error("保存失败")}})},del(id) {this.request.delete("/user/" + id).then(res => {if (res.data) {this.$message.success("删除成功")this.load()} else {this.$message.error("删除失败")}})},delBatch() {let ids = this.multipleSelection.map(v => v.id)  // [{}, {}, {}] => [1,2,3]this.request.post("/user/del/batch", ids).then(res => {if (res.data) {this.$message.success("批量删除成功")this.load()} else {this.$message.error("批量删除失败")}})},

UserDto

import lombok.Data;@Data
public class UserDto {private String username;private String password;private String nickname;private String avatarUrl;
}

Constants.java(常量类,定义Code)

public interface Constants {String CODE_200 = "200"; //成功String CODE_401 = "401";  // 权限不足String CODE_400 = "400";  // 参数错误String CODE_500 = "500"; // 系统错误String CODE_600 = "600"; // 其他业务异常}

Result

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 接口统一返回包装类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private String code;private String msg;private Object data;public static Result success() {return new Result(Constants.CODE_200, "", null);}public static Result success(Object data) {return new Result(Constants.CODE_200, "", data);}public static Result error(String code, String msg) {return new Result(code, msg, null);}public static Result error() {return new Result(Constants.CODE_500, "系统错误", null);}}

ServiceException.java(自定义业务异常)

import lombok.Getter;/*** 自定义异常*/
@Getter
public class ServiceException extends RuntimeException {private String code;public ServiceException(String code, String msg) {super(msg);this.code = code;}}

GlobalExceptionHandler.java

import com.example.springboot.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
public class GlobalExceptionHandler {/*** 如果抛出的的是ServiceException,则调用该方法* @param se 业务异常* @return Result*/@ExceptionHandler(ServiceException.class)@ResponseBodypublic Result handle(ServiceException se){return Result.error(se.getCode(), se.getMessage());}}

头像,昵称功能实现:

Header.vue

<div style="display: inline-block"><img :src="user.avatarUrl" referrerpolicy="no-referrer" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i></div>

UserDto

@Data
public class UserDto {private String username;private String password;@Alias("nickname")private String nickname;private String avatarUrl;
}

四、个人信息页面显示

Person.vue

<template><el-card style="width: 500px;"><el-form label-width="80px" size="small"><el-form-item label="用户名"><el-input v-model="form.username" autocomplete="off"></el-input></el-form-item><el-form-item label="昵称"><el-input v-model="form.nickname" autocomplete="off"></el-input></el-form-item><el-form-item label="邮箱"><el-input v-model="form.email" autocomplete="off"></el-input></el-form-item><el-form-item label="电话"><el-input v-model="form.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="地址"><el-input v-model="form.address" autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="primary" @click="save">确 定</el-button></el-form-item></el-form></el-card>
</template><script>
export default {name: "Person",data() {return {form: {},user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}}},created() {this.request.get("user/findUserName/" + this.user.username).then(res => {if (res.code === '200') {this.form = res.data}})},methods: {save() {this.request.post("/user/saveUser", this.form).then(res => {if (res.data) {this.$message.success("保存成功")} else {this.$message.error("保存失败")}})},}
}
</script><style></style>

UserController

 @GetMapping("/findUserName/{username}")public Result findByName(@PathVariable String username){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",username);return Result.success(userService.getOne(queryWrapper));}

用result封装方法

UserController

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springboot.common.Constants;
import com.example.springboot.common.Result;
import com.example.springboot.entity.User;
import com.example.springboot.entity.dto.UserDto;
import com.example.springboot.service.UserService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;import static com.example.springboot.common.Result.success;@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@GetMapping("/findUserName/{username}")public Result findByName(@PathVariable String username){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",username);return Result.success(userService.getOne(queryWrapper));}//登录@PostMapping("/login")public Result login(@RequestBody UserDto userDto) {String username = userDto.getUsername();String password = userDto.getPassword();if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {return Result.error(Constants.CODE_400, "系统错误");}UserDto dto = userService.login(userDto);return success(dto);}//注册@PostMapping("/register")public Result register(@RequestBody UserDto userDto) {String username = userDto.getUsername();String password = userDto.getPassword();if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {return Result.error(Constants.CODE_400, "系统错误");}return success(userService.register(userDto));}//导入@PostMapping("/import")public Result imp(MultipartFile file) throws Exception {InputStream inputStream = file.getInputStream();ExcelReader reader = ExcelUtil.getReader(inputStream);//方式1(推荐) 通过javabean的方式读取Excel内的对象 但是要求表头必须是英文,跟javabean的属性要对应起来/*List<User> list = reader.readAll(User.class);*///方式二:忽略表头的中文 直接读取表内容List<List<Object>> list = reader.read(1);List<User> users = CollUtil.newArrayList();for (List<Object> row : list) {User user = new User();user.setUsername(row.get(0).toString());user.setPassword(row.get(1).toString());user.setNickname(row.get(2).toString());user.setEmail(row.get(3).toString());user.setPhone(row.get(4).toString());user.setAddress(row.get(5).toString());user.setAvatarUrl(row.get(6).toString());users.add(user);}userService.saveBatch(users);return success(true);}//导出@GetMapping("/export")public Result export(HttpServletResponse response) throws Exception {//从数据库查询出所有数据List<User> list = userService.list();//通过工具类创建writer写出到磁盘路径/*ExcelWriter writer = ExcelUtil.getWriter(filesUploadPath+"/用户信息.xlsx");*///在内存操作,写出到浏览器ExcelWriter writer = ExcelUtil.getWriter(true);//自定义标签别名writer.addHeaderAlias("username", "用户名");writer.addHeaderAlias("password", "密码");writer.addHeaderAlias("nickname", "昵称");writer.addHeaderAlias("email", "邮箱");writer.addHeaderAlias("phone", "电话");writer.addHeaderAlias("address", "地址");writer.addHeaderAlias("createTime", "创建时间");writer.addHeaderAlias("avatarUrl", "头像");//一次性写出list内的对象到excel。使用默认样式,强制输出标题writer.write(list, true);//响应浏览器响应的格式response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");String fileName = URLEncoder.encode("用户信息", "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");ServletOutputStream out = response.getOutputStream();writer.flush(out, true);out.close();writer.close();return Result.success();}//修改或增加@PostMapping("/saveUser")public Result saveUser(@RequestBody User user) {//新增或修改return success(userService.saveOrUpdate(user));}@GetMapping("/findAll")public Result findAll() {return success(userService.list());}@DeleteMapping("/{id}")public Result delete(@PathVariable("id") Integer id) {return success(userService.removeById(id));}//批量删除@PostMapping("/del/batch")public Result deleteBatch(@RequestBody List<Integer> ids) {return success(userService.removeBatchByIds(ids));}//分页查询//接口路径 /user/selectPage?pageNum = 1 &pageSize = 10//@RequestParam 接收//limit第一个参数 = (pageNum - 1)*pageSize//pageSize/* @GetMapping("/selectPage")public Map<String, Object> selectPage(@RequestParam String username, @RequestParam Integer pageSize, @RequestParam Integer pageNum) {pageNum = (pageNum - 1) * pageSize;username = "%" + username + "%";List<User> data = userService.selectPage(pageNum, pageSize, username);Integer total = userService.selectTotal(username);Map<String, Object> res = new HashMap<>();res.put("data", data);res.put("total", total);return res;}*///分页查询 mybatis-plus方式@GetMapping("/selectPage")public Result selectPage(@RequestParam(defaultValue = "") String username,@RequestParam Integer pageSize,@RequestParam Integer pageNum,@RequestParam(defaultValue = "") String email,@RequestParam(defaultValue = "") String address) {IPage<User> page = new Page<>(pageNum, pageSize);QueryWrapper<User> queryWrapper = new QueryWrapper<>();if (!"".equals(username)) {queryWrapper.like("username", username);}if (!"".equals(email)) {queryWrapper.like("email", email);}if (!"".equals(address)) {queryWrapper.like("address", address);}queryWrapper.orderByDesc("id");return success(userService.page(page, queryWrapper));}
}


http://www.ppmy.cn/news/668376.html

相关文章

mybatis模拟05

SqlSession 添加 selectOne(String sqlId, Object data) method /*** description 查询一条数据* param sqlId&#xff1a;sql 语句的 id* param data:所需要的数据 * return result 查询结果*/ public Object selectOne(String sqlId, Object data){return null; } 实现 …

【Express】express注意点

express版本 5.x post的body 5.x版本无需安装 body-parser 中间件&#xff0c;只需简单配置即可使用body↓ 码 import express from express const app express() // 配置post的body app.use(express.json()) app.use(express.urlencoded({ extended: true }))app.post(/tes…

苹果6发布时间_2020苹果发布会直播入口+直播时间

阅读本文前&#xff0c;请您先点击上面的“蓝色字体”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到文章了。每天都有分享&#xff0c;完全是免费订阅&#xff0c;请放心关注。 注&#xff1a;本文转载自网络&#xff0c;不代表本平台立场&#xff0c;仅供读…

苹果iOS 17正式发布!

手机中国新闻】北京时间6月6日凌晨1点&#xff0c;苹果正式召开WWDC开发者大会&#xff0c;全新的iOS 17系统正式发布。 据介绍&#xff0c;iOS 17系统的iMessage新增了check in功能&#xff0c;这是一种便捷、能保护隐私的位置分享功能。它可以告诉你的亲人朋友们你所在的位置…

Vue.js的响应式原理

一、Vue 2 响应式原理 Vue.js是一个渐进式的JavaScript框架&#xff0c;它使用了响应式系统来维护应用程序的状态。响应式系统是Vue.js的核心部分&#xff0c;它使得应用程序能够自动地更新视图&#xff0c;当数据发生变化时。 在Vue.js中&#xff0c;响应式系统使用了一种叫…

消息中间件进阶学习

文章目录 1、RabbitMQ1.1、如何保证消息不丢失&#xff1f;小总结面试快速答法 1.2、消息的重复消费问题面试快速答法 1.3、死信交换机小总结面试快速答法 1.4、消息堆积怎么解决小总结面试快速答法 1.5、集群小总结面试快速答法 2、Kafka2.1、Kafka是如何保证消息不丢失小总结…

JAVA控制台下:商城购物系统(一)数据库设计

前言&#xff1a; 一、数据库设计&#xff1a; /* Navicat MySQL Data TransferSource Server : 127.0.0.1_3306 Source Server Version : 50549 Source Host : 127.0.0.1:3306 Source Database : javashopTarget Server Type : MYSQL Target Se…

09_商品规格管理

点击一个商品 2.商品spu的id会带过来 3.根据spu的id, 查询spu信息&#xff0c; spu信息里有三级分类id&#xff0c; 4.根据三级分类Id定位到规格参数组 参数组渲染在页面的绿色箭头指的地方 5.根据gid查询组下有哪些参数&#xff0c;渲染到 6.怎么获取参数对应的值&a…