前端代码
Header.vue
获取登录用户的昵称在Header进行显示,加入个人信息的路由
<template>
<div style="line-height: 60px; display: flex">
<div style="flex: 1;">
<span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span>
<el-breadcrumb separator="/" style="display: inline-block; margin-left: 10px">
<el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
<el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<el-dropdown style="width: 100px; cursor: pointer;">
<div style="display: inline-block">
<img :src="user.avatarUrl" 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>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 14px; padding: 5px 0">
<router-link to="/person">个人信息</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 14px; padding: 5px 0">
<router-link to="/login" style="text-decoration: none">退出</router-link>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
name: "Header",
props: {
collapseBtnClass: String,
},
computed: {
currentPathName () {
return this.$store.state.currentPathName; //需要监听的数据
}
},
data() {
return {
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
}
},
methods: {
collapse() {
// this.$parent.$parent.$parent.$parent.collapse() // 通过4个 $parent 找到父组件,从而调用其折叠方法
this.$emit("asideCollapse")
},
logout() {
this.$router.push("/login")
localStorage.removeItem("user")
this.$message.success("退出成功")
}
}
}
</script>
<style scoped>
</style>
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" @click="$router.push('/register')">注册</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>
Register.vue
<template>
<div class="wrapper">
<div style="margin: 150px auto; background-color: #fff; width: 350px; height: 350px; 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" prefix-icon="el-icon-user" v-model="user.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input placeholder="请输入密码" size="medium" 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" 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="login">注册</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: {
login() {
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("注册成功")
} else {
this.$message.error(res.msg)
}
})
}
});
}
}
}
</script>
<style>
.wrapper {
height: 100vh;
background-image: linear-gradient(to bottom right, #FC466B , #3F5EFB);
overflow: hidden;
}
</style>
User.vue
接口改造res->res.data
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="username"></el-input>
<el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5" v-model="email"></el-input>
<el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5" v-model="address"></el-input>
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
<el-button type="warning" @click="reset">重置</el-button>
</div>
<div style="margin: 10px 0">
<el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定批量删除这些数据吗?"
@confirm="delBatch"
>
<el-button type="danger" slot="reference">批量删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
<el-upload action="http://localhost:9090/user/import" :show-file-list="false" accept="xlsx" :on-success="handleExcelImportSuccess" style="display: inline-block">
<el-button type="primary" class="ml-5">导入 <i class="el-icon-bottom"></i></el-button>
</el-upload>
<el-button type="primary" @click="exp" class="ml-5">导出 <i class="el-icon-top"></i></el-button>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="'headerBg'" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="username" label="用户名" width="140"></el-table-column>
<el-table-column prop="nickname" label="昵称" width="120"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="success" @click="handleEdit(scope.row)">编辑 <i class="el-icon-edit"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="del(scope.row.id)"
>
<el-button type="danger" slot="reference">删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%" >
<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>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "User",
data() {
return {
tableData: [],
total: 0,
pageNum: 1,
pageSize: 10,
username: "",
email: "",
address: "",
form: {},
dialogFormVisible: false,
multipleSelection: []
}
},
created() {
this.load()
},
methods: {
load() {
this.request.get("/user/page", {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
username: this.username,
email: this.email,
address: this.address,
}
}).then(res => {
console.log(res)
this.tableData = res.data.records
this.total = res.data.total
})
},
save() {
this.request.post("/user", this.form).then(res => {
if (res.data) {
this.$message.success("保存成功")
this.dialogFormVisible = false
this.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("批量删除失败")
}
})
},
handleAdd() {
this.dialogFormVisible = true
this.form = {}
},
handleEdit(row) {
this.form = row
this.dialogFormVisible = true
},
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
},
reset() {
this.username = ""
this.email = ""
this.address = ""
this.load()
},
handleSizeChange(pageSize) {
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum) {
console.log(pageNum)
this.pageNum = pageNum
this.load()
},
exp() {
window.open("http://localhost:9090/user/export")
},
handleExcelImportSuccess() {
this.$message.success("导入成功")
this.load()
}
}
}
</script>
<style>
.headerBg {
background: #eee!important;
}
</style>
Person.vue
增加个人信息页
<template>
<div>
<el-card style="width: 500px;">
<el-form label-width="80px" size="small">
<el-form-item label="用户名">
<el-input v-model="form.username" disabled 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 type="textarea" 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>
</div>
</template>
<script>
export default {
name: "Person",
data() {
return {
form: {},
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
}
},
created() {
this.request.get("/user/username/" + this.user.username).then(res => {
if(res.code === '200') {
this.form = res.data
}
})
},
methods: {
save() {
this.request.post("/user", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功")
} else {
this.$message.error("保存失败")
}
})
},
}
}
</script>
<style scoped>
</style>
router/index.js
加入注册页面与个人信息页面的路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from "@/store";
//import store from "../store"
Vue.use(VueRouter)
const routes = [
{
path: '/',
component: () => import('../views/Manage.vue'),
redirect: "/home",
children: [
{ path: 'home', name: '首页', component: () => import('../views/Home.vue')},
{ path: 'user', name: '用户管理', component: () => import('../views/User.vue')},
{ path: 'person', name: '用户管理', component: () => import('../views/Person.vue')},
]
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: () => import('../views/Login.vue')
},
{
path: '/register',
name: 'Register',
component: () => import('../views/Register.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
// 路由守卫
router.beforeEach((to, from, next) => {
localStorage.setItem("currentPathName", to.name) // 设置当前的路由名称,为了在Header组件中去使用
store.commit("setPath") // 触发store的数据更新
next() // 放行路由
})
export default router
后端代码
UserDTO.java (User包装类)
登录用户实体类加入昵称和头像属性
package com.zj.demo.controller.dao;
import lombok.Data;
/**
* 接受前端登录请求的参数
*/
@Data
public class UserDTO {
private String username;
private String password;
private String nickname;
private String avatarUrl;
}
Result.java【接口统一改造】
之前的接口返回类型有Boolean也有List不统一,前端需要处理多种返回类型,不太合理,所以需要进行统一接口改造
新建common包,创建Result类,具体代码如下
package com.zj.demo.common;
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);
}
}
Constants.java(常量类,定义状态码Code)
package com.zj.demo.common;
public interface Constants {
String CODE_200 = "200"; //成功
String CODE_401 = "401"; // 权限不足
String CODE_400 = "400"; // 参数错误
String CODE_500 = "500"; // 系统错误
String CODE_600 = "600"; // 其他业务异常
}
UserController.java
使用同一接口类型替换之前的返回类型
package com.zj.demo.controller;
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.extension.plugins.pagination.Page;
import com.zj.demo.common.Constants;
import com.zj.demo.common.Result;
import com.zj.demo.controller.dao.UserDTO;
import com.zj.demo.entity.User;
import com.zj.demo.service.IUserService;
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;
/**
* <p>
* 前端控制器
* </p>
*
* @author Joyce
* @since 2023-01-04
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private IUserService userService;
/**
* 登录界面
*/
@PostMapping("/login")
public Result login(@RequestBody UserDTO userDTO)
{
String username = userDTO.getUsername();
String password = userDTO.getPassword();
//判断用户名和密码是否为空[HUTOOL工具包]
if(StrUtil.isBlank(username) || StrUtil.isBlank(password))
{
return Result.error(Constants.CODE_400,"参数错误");
}
UserDTO dto = userService.login(userDTO);
return Result.success(dto);
}
@PostMapping("/register")
public Result register(@RequestBody UserDTO userDTO)
{
String username = userDTO.getUsername();
String password = userDTO.getPassword();
//判断用户名和密码是否为空[HUTOOL工具包]
if(StrUtil.isBlank(username) || StrUtil.isBlank(password))
{
return Result.error(Constants.CODE_400,"参数错误");
}
User dto = userService.register(userDTO);
return Result.success(dto);
}
// 新增或者更新
@PostMapping
public Result save(@RequestBody User user) {
return Result.success(userService.saveOrUpdate(user));
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(userService.removeById(id));
}
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(userService.removeByIds(ids));
}
@GetMapping
public Result findAll() {
return Result.success(userService.list());
}
@GetMapping("/{id}")
public Result findOne(@PathVariable Integer id) {
return Result.success(userService.getById(id));
}
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue ="") String username,
@RequestParam(defaultValue ="") String email,
@RequestParam(defaultValue ="") String address
) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (!"".equals(username)) {
queryWrapper.like("username", username);
}
if (!"".equals(email)) {
queryWrapper.like("nickname", email);
}
//和上面的if判断效果一样
queryWrapper.like(!address.equals(""),"address", address);
queryWrapper.orderByDesc("id");
return Result.success(userService.page(new Page<>(pageNum, pageSize), queryWrapper));
}
/**
* 导出接口
*/
@GetMapping("/export")
public void 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();
}
/**
* excel 导入
* @param file
* @throws Exception
*/
@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);
// 方式2:忽略表头的中文,直接读取表的内容
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 Result.success(true);
}
@GetMapping("/username/{username}")
public Result findOne(@PathVariable String username) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", username);
return Result.success(userService.getOne(queryWrapper));
}
}
UserService.java
之前登陆返回类型Boolean的需要改为UserDTO【因为需要获取用户信息用以登录后首页Header显示】
还有注册功能的加入
package com.zj.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zj.demo.controller.dao.UserDTO;
import com.zj.demo.entity.User;
/**
* <p>
* 服务类
* </p>
*
* @author Joyce
* @since 2023-01-04
*/
public interface IUserService extends IService<User> {
UserDTO login(UserDTO userDTO);
User register(UserDTO userDTO);
}
UserServiceImpl.java
相应的登陆代码修改以及编写注册服务
package com.zj.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zj.demo.common.Constants;
import com.zj.demo.controller.dao.UserDTO;
import com.zj.demo.entity.User;
import com.zj.demo.exception.ServiceException;
import com.zj.demo.mapper.UserMapper;
import com.zj.demo.service.IUserService;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author Joyce
* @since 2023-01-04
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
private static final Log LOG = Log.get();
@Override
public 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, "用户名或密码错误");
}
}
@Override
public User register(UserDTO userDTO) {
User one = getUserInfo(userDTO);
if (one == null) {
one = new User();
BeanUtil.copyProperties(userDTO, one, true);
save(one); // 把 copy完之后的用户对象存储到数据库
} else {
throw new ServiceException(Constants.CODE_600, "用户已存在");
}
return one;
}
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;
}
}
涉及到自定义异常,下面进行编写
GlobalExceptionHandler.java
全局异常处理器编写
package com.zj.demo.exception;
import com.zj.demo.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)
@ResponseBody
public Result handle(ServiceException se){
return Result.error(se.getCode(), se.getMessage());
}
}
ServiceException.java(自定义业务异常)
自定义异常类【包含我们自定义的状态码,以及错误msg】
全局异常会调用该类用来返回服务异常情况下的的状态码以及错误信息
PS: RuntimeException是java提供的一种运行异常,我们自定义的异常需要继承它
package com.zj.demo.exception;
import lombok.Getter;
/**
* 自定义异常
*/
@Getter
public class ServiceException extends RuntimeException {
private String code;
public ServiceException(String code, String msg) {
super(msg);
this.code = code;
}
}
页面测试
登录页面