我们接着上一课的内容继续
我还是尽量把全部代码都贴出来,方便大家学习。
项目结构截图
springboot后端
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</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>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- jwt验证 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
</dependencies>
application.properties
server.port=8089
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=UTC
spring.datasource.username=root
spring.datasource.password=mysql123
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置别名
mybatis-plus.type-aliases-package=com.shrimpking.pojo
#开启逻辑删除,标识字段
mybatis-plus.global-config.db-config.logic-delete-field=is_deleted
#删除
mybatis-plus.global-config.db-config.logic-delete-value=1
#未删除
mybatis-plus.global-config.db-config.logic-not-delete-value=0
#swagger
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
pojo
TestOne.java
package com.shrimpking.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/9 20:51
*/
@Data
@AllArgsConstructor
public class TestOne
{
private int id;
private String name;
private String sex;
private String phone;
}
User.java
package com.shrimpking.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 用户表
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("an_user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "性别")
private String sex;
@ApiModelProperty(value = "电话")
private String phone;
@TableField(exist = false)
private String token;
}
mapper
userMapper.java
package com.shrimpking.mapper;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shrimpking.req.QueryParams;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
public interface UserMapper extends BaseMapper<User> {
/**
* 基于注解的方式
* @return
*/
@Select("select * from an_user")
List<User> getUsers();
/**
* 基于MapperXml的方式
* @return
*/
List<User> getAllUsers();
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch2(@Param("queryParams") QueryParams queryParams);
}
MapperXml
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shrimpking.mapper.UserMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.shrimpking.pojo.User">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="password" property="password" />
<result column="age" property="age" />
<result column="sex" property="sex" />
<result column="phone" property="phone" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, password, age, sex, phone
</sql>
<!-- 基于MapperXml的方式 -->
<select id="getAllUsers" resultType="com.shrimpking.pojo.User">
select <include refid="Base_Column_List"/> from an_user
</select>
<!-- 基于MapperXml的方式,有条件时,获取全部数据 -->
<select id="findBySearch2" resultType="com.shrimpking.pojo.User">
select <include refid="Base_Column_List"/> from an_user
<where>
<if test="queryParams != null and queryParams.name != null and queryParams.name != ''">
or name like concat('%',#{queryParams.name},'%')
</if>
<if test="queryParams != null and queryParams.phone != null and queryParams.phone != ''">
or phone like concat('%',#{queryParams.phone},'%')
</if>
</where>
</select>
</mapper>
service
UserService.java
package com.shrimpking.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shrimpking.req.QueryParams;
import com.shrimpking.res.Result;
import java.util.List;
/**
* <p>
* 用户表 服务类
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
public interface UserService extends IService<User> {
/**
* 基础注解的方式
* @return
*/
List<User> getUsers();
/**
* 基于MapperXml的方式
* @return
*/
List<User> getAllUsers();
/**
* 有查询条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch(QueryParams queryParams);
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch2(QueryParams queryParams);
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
IPage<User> findBySearchPage(QueryParams queryParams);
User login(User user);
}
serviceImpl
UserServiceImpl.java
package com.shrimpking.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.mapper.UserMapper;
import com.shrimpking.req.QueryParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shrimpking.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 用户表 服务实现类
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
/**
* 基于注解的方式
* @return
*/
@Override
public List<User> getUsers()
{
return this.userMapper.getUsers();
}
/**
* 基于MapperXml的方式
* @return
*/
@Override
public List<User> getAllUsers()
{
return this.userMapper.getAllUsers();
}
/**
* 有查询条件,获取全部数据
* @param queryParams
* @return
*/
@Override
public List<User> findBySearch(QueryParams queryParams)
{
//声明查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//姓名不为空,有条件值时,加入此条件
queryWrapper.like(
StringUtils.isNotBlank(queryParams.getName()),
User::getName,queryParams.getName())
//电话不为空,有条件值时,加入此条件
.or().like(
StringUtils.isNotBlank(queryParams.getPhone()),
User::getPhone,queryParams.getPhone());
//返回结果
return this.baseMapper.selectList(queryWrapper);
}
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
@Override
public List<User> findBySearch2(QueryParams queryParams)
{
return this.userMapper.findBySearch2(queryParams);
}
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
@Override
public IPage<User> findBySearchPage(QueryParams queryParams)
{
//声明分页
IPage<User> page = new Page<>(queryParams.getCurrentPage(),queryParams.getPageSize());
//声明查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//姓名不为空,有条件值时,加入此条件
queryWrapper.like(
StringUtils.isNotBlank(queryParams.getName()),
User::getName,queryParams.getName())
//电话不为空,有条件值时,加入此条件
.or().like(
StringUtils.isNotBlank(queryParams.getPhone()),
User::getPhone,queryParams.getPhone())
.orderByDesc(User::getId);
//返回结果
return this.baseMapper.selectPage(page, queryWrapper);
}
@Override
public User login(User user)
{
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
User one = this.baseMapper.selectOne(queryWrapper);
if(one == null || !one.getPassword().equals(user.getPassword())){
throw new CustomException("用户名或密码错误");
}
//如果查询出来,有用户,生成token,与user一起返回
String token = JwtUtils.createToken(one.getId().toString(), one.getPassword());
one.setToken(token);
//屏蔽密码
one.setPassword("***");
return one;
}
}
controller
TsetController.java
package com.shrimpking.controller;
import com.shrimpking.pojo.TestOne;
import com.shrimpking.res.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/9 20:45
*/
@RestController
@RequestMapping("/test")
public class TestController
{
@RequestMapping(value = "/start",method = RequestMethod.GET)
public String start(){
return "这是你的第一个springboot工程项目!已经启动!";
//http://localhost:8089/test/start
}
@GetMapping("/getOne")
public TestOne getTestOne(){
return new TestOne(1,"tom","男","13000000000");
//http://localhost:8089/test/getOne
//{"id":1,"name":"tom","sex":"男","phone":"13000000000"}
}
@GetMapping("/start2")
public Result start2(){
return Result.success("这是你的第一个springboot工程项目!已经启动!");
//http://localhost:8089/test/start2
//{"code":"200","msg":"成功","data":"这是你的第一个springboot工程项目!已经启动!"}
}
@GetMapping("/getOne2")
public Result getTestOne2(){
return Result.success(new TestOne(2,"jerry","女","138999988888"));
//http://localhost:8089/test/getOne2
//{"code":"200","msg":"成功","data":{"id":2,"name":"jerry","sex":"女","phone":"138999988888"}}
}
}
UserController.java
package com.shrimpking.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.req.QueryParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.UserService;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* <p>
* 用户表 前端控制器
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 3基于mybatisplus的方式
* @return
*/
@GetMapping("/getList")
public List<User> getUserList(){
return this.userService.list();
//http://localhost:8089/user/getList
}
/**
* 2基于注解的方式
*
* @return
*/
@GetMapping("/getUsers")
public List<User> getUsers(){
return this.userService.getUsers();
//http://localhost:8089/user/getUsers
//[{"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]
}
/**
* 1基于MapperXml的方式
* @return
*/
@GetMapping("/getAll")
public List<User> getAllUsers(){
return this.userService.getAllUsers();
//http://localhost:8089/user/getAll
//[{"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]
}
/**
* 3基于mybatisplus的方式
* @return
*/
@GetMapping("/getList2")
public Result getUserList2(){
return Result.success(this.userService.list());
//http://localhost:8089/user/getList2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 2基于注解的方式
*
* @return
*/
@GetMapping("/getUsers2")
public Result getUsers2(){
return Result.success(this.userService.getUsers());
//http://localhost:8089/user/getUsers2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 1基于MapperXml的方式
* @return
*/
@GetMapping("/getAll2")
public Result getAllUsers2(){
return Result.success(this.userService.getUsers());
//http://localhost:8089/user/getAll2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 获取全部数据
* @return
*/
@GetMapping("/findAll")
public Result findAll(){
return Result.success(this.userService.list());
}
/**
* 有查询条件时,获取全部数据
* @param queryParams
* @return
*/
@GetMapping("/search")
public Result findBySearch(QueryParams queryParams){
List<User> list = this.userService.findBySearch(queryParams);
return Result.success(list);
}
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
@GetMapping("/search2")
public Result findBySearch2(QueryParams queryParams){
List<User> list = this.userService.findBySearch2(queryParams);
return Result.success(list);
}
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
@GetMapping("/searchPage")
public Result findBySearchPage(QueryParams queryParams){
IPage<User> list = this.userService.findBySearchPage(queryParams);
return Result.success(list);
}
@PostMapping("/save")
public Result save(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
int count = this.userService.count(queryWrapper);
if(count > 0) return Result.error("此用户名已存在");
boolean save = this.userService.save(user);
if(!save) return Result.error("保存失败");
return Result.success("保存成功");
}
@PostMapping("/update")
public Result update(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
User one = this.userService.getOne(queryWrapper);
if(one != null && !one.getId().equals(user.getId())){
return Result.error("此用户名已存在");
}
boolean save = this.userService.updateById(user);
if(!save) return Result.error("更新失败");
return Result.success("更新成功");
}
@DeleteMapping("/delete")
public Result delete(@RequestParam("id") Integer id){
boolean remove = this.userService.removeById(id);
if(!remove) return Result.error("删除失败");
return Result.success("删除成功");
}
@PostMapping("/login")
public Result login(@RequestBody User user){
User login = this.userService.login(user);
return Result.success(login);
}
@PostMapping("/register")
public Result register(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
int count = this.userService.count(queryWrapper);
if(count > 0) {
throw new CustomException("此用户已经存在,请重新注册!");
}
boolean save = this.userService.save(user);
if(!save) return Result.error("注册失败");
return Result.success("注册成功");
}
}
config
apiConfig.java
package com.shrimpking.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/12 14:39
*/
@Configuration
public class ApiConfig implements WebMvcConfigurer
{
@Override
public void configurePathMatch(PathMatchConfigurer configurer)
{
//指定controller的统一接口前缀,增加接口前缀
configurer.addPathPrefix("/api",clazz-> clazz.isAnnotationPresent(RestController.class));
}
}
corsConfig.java
package com.shrimpking.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
// 案例 一
@Configuration
public class CorsConfig implements WebMvcConfigurer
{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//放行哪些原始域
.allowedOriginPatterns("*")
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
/**
* 增加了自定义拦截器后,需要使用此方法,才可以解决跨域,
* 前一个方法maps,自动失效了。
* @return
*/
@Bean
public CorsFilter corsFilter(){
//添加cors配置
CorsConfiguration config = new CorsConfiguration();
//允许的域,不要写*号
config.addAllowedOrigin("http://localhost:8080");
//是否发送cookie
config.setAllowCredentials(true);
//允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
//允许的头信息
config.addAllowedHeader("*");
//添加映射路径
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**",config);
return new CorsFilter(configurationSource);
}
}
jwtCofig.java
package com.shrimpking.config;
import com.shrimpking.interceptor.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/12 14:39
*/
@Configuration
public class JwtConfig implements WebMvcConfigurer
{
@Autowired
private JwtInterceptor jwtInterceptor;
/**
* 添加jwt拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/user/login")
.excludePathPatterns("/api/user/register");
}
}
mybatisplusConfig.java
package com.shrimpking.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.shrimpking.mapper")
public class MybatisPlusConfig
{
/**
* 配置分页插件的
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor()
{
MybatisPlusInterceptor interceptor
= new MybatisPlusInterceptor();
//分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//防止全表更新插件
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
}
swaggerConfig.java
package com.shrimpking.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/9/10 14:58
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("系统接口文档")
.description("接口文档的描述")
.version("1.0")
.contact(new Contact("weixin","http://www.baidu.com","[email protected]"))
.build();
}
}
exception
CustomException.java
package com.shrimpking.exception;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/11 11:04
*/
public class CustomException extends RuntimeException
{
private String message;
public CustomException(String message)
{
this.message = message;
}
@Override
public String getMessage()
{
return this.message;
}
}
globalException.java
package com.shrimpking.exception;
import com.shrimpking.res.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/11 11:01
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler
{
@ExceptionHandler(Exception.class)
public Result error(HttpServletRequest request,Exception e){
log.error("异常信息:",e);
return Result.error("系统异常");
}
@ExceptionHandler(CustomException.class)
public Result customException(HttpServletRequest request,CustomException e){
log.error("异常信息:",e);
return Result.error(e.getMessage());
}
}
interceptor
jwtInterceptor.java
package com.shrimpking.interceptor;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shrimpking.exception.CustomException;
import com.shrimpking.service.UserService;
import com.shrimpking.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/12 16:21
*/
@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor
{
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
//获取token,从请求头部获取
String token = request.getHeader("z-token");
if(StringUtils.isBlank(token)){
//token为空,从请求参数获取
token = request.getParameter("token");
}
//token为空,重新登录
if(StringUtils.isBlank(token)){
throw new CustomException("获取token失败,请重新登录!");
}
//验证解析token
return JwtUtils.verify(token);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
}
}
req
QueryParams.java
package com.shrimpking.req;
import lombok.Data;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/10 12:27
*/
@Data
public class QueryParams
{
private String name;
private String phone;
private Long currentPage;
private Long pageSize;
}
res
result.java
package com.shrimpking.res;
import lombok.Data;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/10 11:03
*/
@Data
public class Result
{
public static final String SUCCESS = "200";
public static final String ERROR = "400";
private String code;
private String msg;
private Object data;
public static Result success(){
Result result = new Result();
result.setCode(SUCCESS);
result.setMsg("成功");
return result;
}
public static Result success(Object data){
Result result = new Result();
result.setCode(SUCCESS);
result.setMsg("成功");
result.setData(data);
return result;
}
public static Result error(String msg){
Result result = new Result();
result.setCode(ERROR);
result.setMsg(msg);
return result;
}
}
utils
jwtUtils.java
package com.shrimpking.utils;
import ch.qos.logback.classic.turbo.TurboFilter;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/12 14:49
*/
@Slf4j
@Component
public class JwtUtils
{
private static UserService staticUserService;
@Autowired
private UserService userService;
@PostConstruct
public void setUserService(){
staticUserService = userService;
}
/**
* 生成token
* @param adminId
* @param sign
* @return
*/
public static String createToken(String userId,String pwdToSign){
return JWT.create()
//将user id保存到里面,作为载荷
.withAudience(userId)
//2个小时以后过期
.withExpiresAt(DateUtil.offsetHour(new Date(),2))
//以password作为签名
.sign(Algorithm.HMAC256(pwdToSign));
}
/**
* 获取当前用户
* @return
*/
public static User getCurrentUser(){
//声明token
String token = null;
try
{
//获取请求
HttpServletRequest request
= ((ServletRequestAttributes)Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
//从请求头部获取token
token = request.getHeader("z-token");
//如果头部没有,请请求参数获取token
if(StringUtils.isBlank(token)){
token = request.getParameter("token");
}
//如果token没有,返回null
if(StringUtils.isBlank(token)){
log.error("获取当前登录用户信息失败,token={}",token);
return null;
}
//解析token
String userId = JWT.decode(token).getAudience().get(0);
//返回用户
return staticUserService.getById(userId);
}catch (Exception e){
log.error("获取当前登录用户信息失败,token={}",token,e);
return null;
}
}
/**
* 验证token
* @param token
* @return
*/
public static Boolean verify(String token){
//用户id
String userId;
//用户
User user;
try
{
//解析token,获取id
userId = JWT.decode(token).getAudience().get(0);
//根据id,获取用户
user = staticUserService.getById(userId);
}catch (Exception e){
String errorMsg = "非法token,验证失败,请重新登录!";
log.error(errorMsg + ",token=" + token ,e);
throw new CustomException(errorMsg);
}
//未查到用户
if(user == null){
throw new CustomException("用户不存在,请重新登录!");
}
try
{
//解析过程中,无异常,说明验证成功
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
verifier.verify(token);
}catch (JWTVerificationException e){
throw new CustomException("token验证失败,请重新登录");
}
return true;
}
}
启动类
package com.shrimpking;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.shrimpking.mapper")
public class SpringbootVueTest31Application
{
public static void main(String[] args)
{
SpringApplication.run(SpringbootVueTest31Application.class, args);
}
}
数据库
drop table if exists an_user;
create table an_user(
id int not null auto_increment primary key comment '主键id',
name varchar(255) not null unique comment '姓名',
`password` varchar(255) not null comment '密码',
age int(3) default null comment '年龄',
sex varchar(10) default null comment '性别',
phone varchar(20) default null comment '电话'
) comment '用户表';
insert into an_user values (1,'zhangsan','1234',33,'男','13300000000');
insert into an_user values (2,'lisi','1234',13,'女','13400000000');
Vue前端
vue.config.js
module.exports = {
transpileDependencies: true
}
package.json
{
"name": "vueweb",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^1.6.1",
"core-js": "^3.8.3",
"echarts": "^5.1.2",
"element-ui": "^2.15.14",
"mockjs": "^1.1.0",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^5.0.0",
"@vue/cli-service": "^5.0.0",
"sass": "^1.32.7",
"sass-loader": "^12.0.0",
"vue-template-compiler": "^2.6.14"
}
}
global.css
html,body{
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/login',
name:'LoginView',
component: ()=> import('@/views/LoginView.vue'),
},
{
path:'/register',
name: 'Register',
component: ()=> import('@/views/RegisterView.vue'),
},
{
path: '/',
redirect: '/home',
name: 'Layout',
component: ()=> import('@/views/Layout.vue'),
children:[
{
path: 'home',
name: 'HomeView',
component: ()=> import('@/views/HomeView.vue')
},
{
path: 'admin',
name: 'AdminView',
component: ()=> import('@/views/User/AdminView.vue'),
},
{
path:'user',
name:'UserView',
component: ()=> import('@/views/User/UserView.vue'),
},
]
},
]
const router = new VueRouter({
routes
})
//白名单
const IGNORE_URLS = ['/login','/register'];
//前置守卫
router.beforeEach((to, from, next) => {
//在白名单中,放行
if(IGNORE_URLS.includes(to.path)){
next();
}
//获取用户
let admin = JSON.parse(window.localStorage.getItem('access-admin'));
if(!admin && !IGNORE_URLS.includes(to.path)){
//没有登录 ,没有在白名单中,跳转登录
return next('/login');
}
next();
});
export default router
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
utils
request.js
import axios from 'axios'
const request = axios.create({
baseURL: 'http://localhost:8089/api', //
timeout: 5000,
});
//request 拦截器
request.interceptors.request.use( config =>{
config.headers['Content-Type'] = 'application/json;charset=utf-8';
//获取token
const admin = JSON.parse(window.localStorage.getItem('access-admin'));
if(admin){
config.headers['z-token'] = admin.token;
}
return config;
},error => {
return Promise.reject(error);
});
//respose 拦截器
request.interceptors.response.use( response => {
//response.data即为后端返回的result, 也就是脱壳
let res = response.data;
//兼容服务端返回的字符串数据
if(typeof res === 'string'){
res = res ? JSON.parse(res) : res;
}
return res;
},error => {
console.log('error:' + error);
return Promise.reject(error);
});
export default request;
main.js
import Vue from 'vue'
import App from './App.vue'
import store from '@/store'
import router from "@/router";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from "axios";
import * as echarts from 'echarts'
import '@/assets/global.css'
Vue.prototype.$echarts = echarts;
axios.defaults.baseURL='http://localhost:8089';
Vue.prototype.$http = axios;
Vue.use(ElementUI,{size:'small'});
Vue.config.productionTip = false;
new Vue({
render: h => h(App),
store,
router
}).$mount('#app');
app.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<style lang="scss">
</style>
register.vue
<template>
<div class="register-area">
<h1 class="title">注册用户</h1>
<el-form
:model="registerForm"
:rules="rules"
ref="registerForm"
class="form-demo"
label-width="100px;"
label-postion="left">
<el-form-item prop="name">
<el-input
v-model="registerForm.name"
placeholder="用户名"
clearable>
<template slot="prepend"><i class="el-icon-user-solid"></i></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="registerForm.password"
placeholder="密码"
show-password
clearable>
<template slot="prepend"><i class="el-icon-lock"></i></template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetBtn" class="reset-btn">重 置</el-button>
</el-form-item>
<el-button type="primary" @click="register" class="register-btn">注 册</el-button>
<el-button type="text" @click="toLogin" class="login-btn">返回登录</el-button>
</el-form>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "RegisterView",
data(){
return {
registerForm: {
name:'',
password:''
},
rules: {
name: [{ required: true ,message: '请输入用户名', trigger: 'blur'}],
password: [{ required: true ,message: '请输入密码', trigger: 'blur'}],
}
}
},
methods: {
//重置
resetBtn(){
this.$refs.registerForm.resetFields();
},
//返回登录
toLogin(){
this.$router.replace('/login');
},
//注册
register(){
this.$refs.registerForm.validate((valid)=>{
if(valid){
request.post('/user/register',this.registerForm)
.then(res=>{
if(res.code === '200'){
this.$message.success(res.msg);
this.$router.replace('/login');
}else {
this.$message.error(res.msg);
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.register-area{
width: 400px;
height: 500px;
border: 1px solid rgba(107,149,224,0.5);
border-radius: 15px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-75%);
padding: 10px;
.title{
text-align: center;
margin-bottom: 30px;
}
.form-demo{
width: 80%;
margin: 0 auto;
.reset-btn{
width: 100%;
margin-top: 24px;
height: 40px;
}
.register-btn{
width: 100%;
height: 40px;
}
.login-btn{
width: 100%;
margin-top: 5px;
text-align: center;
}
}
}
</style>
login.vue
<template>
<div class="register-area">
<h1 class="title">手牵手带小白做毕设</h1>
<el-form
:model="loginForm"
:rules="rules"
ref="loginForm"
class="form-demo"
label-width="100px;"
label-postion="left">
<el-form-item prop="name">
<el-input
v-model="loginForm.name"
placeholder="用户名"
clearable>
<template slot="prepend"><i class="el-icon-user-solid"></i></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
placeholder="密码"
show-password
clearable>
<template slot="prepend"><i class="el-icon-lock"></i></template>
</el-input>
</el-form-item>
<el-button type="primary" @click="login" class="login-btn">登 录</el-button>
<el-button type="text" @click="toRegister" class="register-btn">没有账号,注册一下</el-button>
</el-form>
<div>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "LoginView",
data(){
return {
loginForm: {
name:'',
password:''
},
rules: {
name: [{ required: true ,message: '请输入用户名', trigger: 'blur'}],
password: [{ required: true ,message: '请输入密码', trigger: 'blur'}],
}
}
},
methods: {
//注册
toRegister(){
this.$router.replace('/register');
},
login(){
this.$refs.loginForm.validate((valid)=>{
if(valid){
request.post('/user/login',this.loginForm)
.then(res=>{
if(res.code === '200'){
this.$message.success(res.msg);
window.localStorage.setItem('access-admin',JSON.stringify(res.data));
this.$router.replace('/home');
}else {
this.$message.error(res.msg);
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.register-area{
width: 400px;
height: 310px;
border-radius: 15px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-75%);
padding: 10px;
background-color: rgba(107,149,224,0.5);
.title{
text-align: center;
margin-bottom: 30px;
}
.form-demo{
width: 80%;
margin: 0 auto;
.login-btn{
width: 100%;
margin-top: 24px;
height: 40px;
}
.register-btn{
width: 100%;
margin-top: 5px;
text-align: center;
color: #ffffff;
}
}
}
</style>
layout.vue
<template>
<div>
<el-container class="container">
<el-header class="header-area">
<img src="@/assets/logo.png" alt="logo" class="logo">
<span class="title">手牵手带小白做毕设</span>
<span class="admin-info">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
用户: <strong>{{ admin.name }}</strong>
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="logout">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</el-header>
<el-container class="middle-area">
<el-aside class="left-aside">
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
router>
<el-menu-item index="/home">
<i class="el-icon-menu"></i>
<span slot="title">系统首页</span>
</el-menu-item>
<el-submenu index="/admin">
<template slot="title">
<i class="el-icon-location"></i>
<span>用户管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/admin">管理员信息</el-menu-item>
<el-menu-item index="/user">用户信息</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/3-1">
<template slot="title">
<i class="el-icon-location"></i>
<span>信息管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="3-1">xxx信息</el-menu-item>
<el-menu-item index="3-2">yyy信息</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Layout",
computed: {
admin(){
return JSON.parse(window.localStorage.getItem('access-admin')) || { name: '未登录'};
}
},
methods: {
//下拉菜单命令
handleCommand(command){
if (command === 'logout') {
this.logout();
}
},
//退出
logout(){
window.localStorage.clear();
this.$message.success('退出成功!');
this.$router.replace('/login');
}
}
}
</script>
<style lang="scss" scoped>
.container{
height: 100vh;
.header-area{
background-color: #4c535a;
.logo {
width: 40px;
position: relative;
top: 10px;
}
.title{
font-size: 20px;
margin-left: 15px;
color: white;
}
.admin-info{
float: right;
margin-right: 30px;
line-height: 60px;
.el-dropdown-link{
color: #cccccc;
}
}
}
.middle-area{
.left-aside{
overflow: hidden;
height: 100%;
/*background-color: #545c64;*/
width:230px !important;
.el-menu-vertical-demo{
height: 100%;
}
}
}
}
</style>
home.vue
<template>
<div>
<div style="font-size: 18px;margin: 15px 0;">手牵手教小白做毕设</div>
<div style="font-size: 18px;margin: 15px 0;">大家给个一键三连</div>
<div style="font-size: 18px;margin: 15px 0;">感谢大家</div>
</div>
</template>
<script>
export default {
name: "HomeView"
}
</script>
<style scoped>
</style>
adminview.vue
<template>
<div>
<!-- 搜索区域 -->
<div style="margin-bottom:15px;">
<el-input
v-model="searchForm.name"
style="width:200px;"
placeholder="请输入姓名"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable>
</el-input>
<el-input
v-model="searchForm.phone"
style="width:200px;margin-left: 10px;"
placeholder="请输入电话"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable>
</el-input>
<el-button
type="warning"
style="margin-left: 10px;"
icon="el-icon-search"
@click="doSearch">查询</el-button>
<el-button
type="primary"
style="margin-left: 10px;"
icon="el-icon-toilet-paper"
@click="clearSearch">清空</el-button>
<el-button
type="primary"
style="margin-left: 10px;"
icon="el-icon-plus" @click="addBtn">新增</el-button>
</div>
<!-- 表格区域 -->
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="id"
label="ID">
</el-table-column>
<el-table-column
prop="name"
label="姓名">
</el-table-column>
<el-table-column
prop="password"
label="密码">
</el-table-column>
<el-table-column
prop="age"
label="年龄">
</el-table-column>
<el-table-column
prop="sex"
label="性别">
</el-table-column>
<el-table-column
prop="phone"
label="电话">
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" @click="editBtn(scope.row)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" @click="deleteBtn(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页区域 -->
<div style="margin-top:15px;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="searchForm.currentPage"
:page-sizes="[2, 5, 10, 20]"
:page-size="searchForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<!-- 对话框 -->
<div>
<el-dialog
:title="dialogTitle"
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
@close="closeDialog"
width="35%">
<el-form
:model="addForm"
:rules="rules"
ref="addForm"
:label-width="formLabelWidth"
label-postion="left">
<el-form-item label="姓名" prop="name">
<el-input v-model="addForm.name" clearable></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addForm.password" clearable></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input-number v-model="addForm.age" :max="199" :min="1" label="描述文字"></el-input-number>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio v-model="addForm.sex" label="男">男</el-radio>
<el-radio v-model="addForm.sex" label="女">女</el-radio>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="addForm.phone" clearable></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetBtn" v-show="dialogTitle === '新增用户'">重 置</el-button>
<el-button type="primary" @click="submitBtn">确 定</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "AdminView",
data() {
return {
//添加表单
addForm:{
name:'',
password:'',
age:'',
sex:'',
phone:''
},
rules:{
name:[{required: true, message: '请输入姓名', trigger: 'blur'}],
password:[{required: true, message: '请输入密码', trigger: 'blur'}],
age:[{required: true, message: '请输入年龄', trigger: 'blur'}],
sex:[{required: true, message: '请选择性别', trigger: 'blur'}],
phone:[{required: true, message: '请输入电话', trigger: 'blur'}],
},
//表单标题宽度
formLabelWidth:'80px',
//对话框标题
dialogTitle:'',
//对话框
dialogFormVisible: false,
//搜索条件
searchForm:{
name: '',
phone: '',
currentPage: 1,
pageSize: 5
},
tableData: [],
total:0
}
},
methods: {
//删除
deleteBtn(row){
this.$confirm(`您确定要删除【${row.name}】吗`,'删除提示',{
confirmButtonText:'删除',
cancelButtonText:'取消',
type:'warning',
}).then(()=>{
request.delete('/user/delete',{
params:{ id : row.id}
}).then(res => {
if(res.code === '200'){
this.$message.success(res.data);
this.doSearch();
}
})
}).catch(_=>{
this.$message.warning('已取消删除');
})
},
//编辑
editBtn(row){
let obj = JSON.parse(JSON.stringify(row));
this.addForm = obj;
this.dialogTitle = "编辑用户";
this.dialogFormVisible = true;
},
//关闭对话框
closeDialog(){
this.resetBtn();
this.dialogFormVisible = false;
},
//新增保存
submitBtn(){
this.$refs.addForm.validate((valid)=>{
if(valid){
//校验通过
//有id,编辑,没有id是新增
request.post(this.addForm.id ? '/user/update':'/user/save',this.addForm)
.then(res=>{
if(res.code === '200'){
this.$message.success(res.data);
this.resetBtn();
this.dialogFormVisible = false;
this.doSearch();
}else {
this.$message.error(res.msg);
}
})
}
})
},
//新增重置
resetBtn(){
this.$refs.addForm.resetFields();
this.addForm = {};
},
addBtn(){
this.dialogTitle = '新增用户';
this.dialogFormVisible = true;
},
clearSearch(){
this.searchForm.name = '';
this.searchForm.phone = '';
this.doSearch();
},
//搜索
doSearch(){
// request.get('/user/search',{
// params: this.searchForm
// }).then(res=>{
// if(res.code === '200'){
// this.tableData = res.data;
// }else {
// this.$message.error("查询失败");
// }
// })
//修复bug
this.searchForm.currentPage = 1;
this.getData();
},
handleSizeChange(val) {
this.searchForm.pageSize = val;
this.getData();
},
handleCurrentChange(val) {
this.searchForm.currentPage = val;
this.getData();
},
//获取数据
getData(){
// request.get('/user/findAll')
// .then(res => {
// if(res.code === '200'){
// this.tableData = res.data;
// }else {
// this.$message.error('获取数据失败');
// }
// });
request.get('/user/searchPage',{
params: this.searchForm
}).then(res=>{
if(res.code === '200'){
//console.log(res)
this.tableData = res.data.records; //数据
this.searchForm.currentPage = res.data.current; //当前页
this.searchForm.pageSize = res.data.size; //页条数
this.total = res.data.total; //总条数
}else {
this.$message.error(res.msg);
}
});
}
},
created(){
//获取数据
this.getData();
}
}
</script>
<style scoped>
</style>
userview.vue
<template>
<div>UserView</div>
</template>
<script>
export default {
name: "UserView"
}
</script>
<style scoped>
</style>