学习SpringBoot基础的练手案例(用户信息管理页面)

题主是仿照的黑马springboot课程里面的图书管理页面,仿照做出了一个用户信息页面

添加

修改信息

删除提示

第四页

查询

具有基础的增删改,按条件查询,分页功能,然后可以对异常信息进行简单处理

怎么实现的呢?

首先是数据库表,起名为tb_user,然后id自增,name和email字段必填,最后是把name作了唯一约束,防止添加重复数据

接着就是建spring boot环境,创建的话我勾了SpringMvc的和MySQL,以下是我的application.yml配置

server:
  port: 8088
spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/spring
      username: root
      password: root
mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_
      id-type: auto
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

maven坐标配置

  <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>

然后这个是我的目录结构

看着好像很多,但是实际就三个层,数据层,业务层,表现层三层。

接着开始第一步,domain目录下建一个User实体类

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    private String address;
    private String description;



}

接着是数据层,dao目录下建一个UserDao接口,使用的Mybatis-plus,继承了BaseMapper<User>

@Mapper
public interface UserDao extends BaseMapper<User> {
}

之后开始做测试工作

test目录下创建一个dao测试类,增删改查,查单个,查全部,分页功能,以下是一个增方法的测试,依次测试

@SpringBootTest
public class UserDaoTestCase {
    @Autowired
    private UserDao userDao;

    @Test
    void testInsert(){
        User user=new User();
        user.setName("老李");
        user.setEmail("212542908@qq.com");

        userDao.insert(user);
    }
}

然后需要说一下分页功能需要一个拦截器才能实现,config目录下创建

@Configuration
public class MPConfig {

    @Bean
    public MybatisPlusInterceptor interceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

}

下一步是做业务层了,需要记住业务层和数据层不太一样,它关注的是业务,而不是具体的操作,这个是你对业务的理解,所以可能出现业务层方法和数据层方法名字不一样的情况。

IUserService接口
public interface IUserService extends IService<User> {
    
    //这个方法后面用不到,可以不写
    public IPage<User> getPage(int currentPage,int pageSize);

    
    public IPage<User> getPage(int currentPage,int pageSize,User user);

}

实现类,同样是MyBatisPlus


@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements IUserService {
    @Autowired
    private UserDao userDao;


    @Override
    public IPage<User> getPage(int currentPage, int pageSize, User user) {
        LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<>();
        lqw.like(Strings.isNotEmpty(user.getName()),User::getName,user.getName());
        lqw.like(Strings.isNotEmpty(user.getAddress()),User::getAddress,user.getAddress());
        lqw.like(Strings.isNotEmpty(user.getDescription()),User::getDescription,user.getDescription());


        IPage page=new Page(currentPage,pageSize);
        userDao.selectPage(page,lqw);
        return page;
    }
    


}

接着是测试业务层方法了。

同数据层做的一样,不过这次建的是Service的测试用例。

@SpringBootTest
public class UserServiceTestCase {

    @Autowired
    private IUserService userService;

    @Test
    void testInsert(){

        User user=new User();
        user.setName("小丽菊");
        user.setEmail("212516523@qq.com");

        userService.save(user);
    }
}

做完之后就到了表现层的模块了

表现层需要做的方法比较多,因为这次没有MyBatis-plus帮我们了,然后解释下为什么要返回一个Result,这个是为了统一数据格式,统一前端接收到的内容不要一下是A类型,一下是B类型,C类型。这个是叫做前后端数据通信协议来着。


@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private IUserService userService;

    @PostMapping
    public Result save(@RequestBody User user) throws Exception {
        if(user.getName().equals("王五")) throw new IOException();

        boolean flag = userService.save(user);
        return new Result(flag,flag?"添加成功":"添加失败");
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id){
        boolean flag = userService.removeById(id);

        return new Result(flag,flag?"删除成功":"数据同步失败,自动刷新");
    }
    @PutMapping
    public Result update(@RequestBody User user){
        boolean flag = userService.updateById(user);

        return new Result(flag,flag?"修改成功":"修改失败");
    }

    @GetMapping
    public Result getAll(){
        List<User> data = userService.list();

        return new Result(true,data,data==null?"您请求的数据不对噢,请重新尝试":"");
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id){
        User data = userService.getById(id);

        return new Result(true,data,data!=null?"":"数据同步失败,自动刷新");
    }

//    @GetMapping("/{currentPage}/{pageSize}")
//    public Result getPage(@PathVariable Integer currentPage, @PathVariable Integer pageSize){
//        IPage<User> data = userService.getPage(currentPage, pageSize);
//
//
//        return new Result(true,data,data==null?"您请求的数据不对噢,请重新尝试":"");
//    }

    @GetMapping("/{currentPage}/{pageSize}")
    public Result getPage(@PathVariable Integer currentPage, @PathVariable Integer pageSize,User user){

        IPage<User> page = userService.getPage(currentPage, pageSize,user);
        if(page.getCurrent()>page.getPages()){
            page=userService.getPage((int)page.getPages(),pageSize,user);
        }


        return new Result(true,page,page==null?"您请求的数据不对噢,请重新尝试":"");
    }

}

然后这个是我的Result类,flag是标志成功不成功,data是数据,msg是返回给前端的信息

@Data
public class Result {
    private Boolean flag;
    private Object  data;
    private String msg;

    public Result(Boolean flag) {
        this.flag = flag;
    }

    public Result(Boolean flag, String msg) {
        this.flag = flag;
        this.msg = msg;
    }

    public Result(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }

    public Result(Boolean flag, Object data, String msg) {
        this.flag = flag;
        this.data = data;
        this.msg = msg;
    }
}

然后还需要做一下异常处理

@RestControllerAdvice
public class ProjectExceptionAdvice {


    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public Result doSqlException(SQLIntegrityConstraintViolationException sql){
        sql.printStackTrace();
        return new Result(false,null,"不能添加重复数据");
    }


    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
        ex.printStackTrace();
        return new Result(false,null,"服务器故障,请联系管理员");
    }



}

虽然我写了一个具体的sql异常,但是不知道为什么,等到了后面测试的时候,一直进的是通用的异常,有点迷惑,不过无伤大雅。

到了这里,后端部分的内容就全部完结了。

接下来是前端相关的,vue2+element-ui,题主之前学过vue2,但是基本忘了很多,所以有些地方的具体逻辑没有去写很清楚

添加方法,axios发送请求,通过表单数据formData去发送,如果flag标志为真,那么把弹窗打开,提示成功,否则提示失败,然后不管成不成功都要通过getAll刷新数据

 //添加
            handleAdd () {

                    axios.post("/users",this.formData).then((res)=>{
                        if(res.data.flag){
                            this.dialogFormVisible=false;
                            this.$message({
                                message: res.data.msg,
                                type: 'success'
                            });
                        }else{
                            this.$message.error(res.data.msg);
                        }

                    }).finally(()=>{
                        this.getAll()
                    })

            },

删除,基本同上

 // 删除
            handleDelete(row) {
                //先提示消息框
                this.$confirm("你确定要删除吗?", "提示", {
                    type: "warning"
                })
                    //点击确定
                    .then(() => {
                        axios.delete("/users/" + row.id).then((res) => {
                            if (res.data.flag) {
                                this.$message.success(res.data.msg);
                            } else {
                                // this.$message.error("删除失败")
                                this.$message.error(res.data.msg);
                            }//不管删除成功还是删除失败,都要刷新页面
                        }).finally(() => {
                            this.getAll()
                        })


                    })
                    //点击取消
                    .catch(() => {
                        this.$message.info("取消操作");
                    })

            },

修改,差不多

 //修改
            handleEdit() {
                axios.put("/users", this.formData).then((res) => {
                    //判断当前操作是否成功
                    if (res.data.flag) {
                        //1:关闭弹层
                        this.dialogFormVisible4Edit = false;
                        this.$message({
                            message: res.data.msg,
                            type: 'success'
                        });

                    } else {
                        this.$message.error(res.data.msg);
                    }
                }).finally(() => {
                    //2:重新加载数据
                    this.getAll()
                })



            },

查找的话是,分页按条件查找去加载数据,但是说白了其实就是写个带分页和带条件的sql语句,没有什么大不了的东西。

  //列表
            getAll() {
                param="?name="+this.pagination.name;
                param+="&address="+this.pagination.address;
                param+="&description="+this.pagination.description;
                // console.log(param)
                axios.get("/users/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res)=>{
                    // console.log(res.data)
                    this.pagination.currentPage=res.data.data.current
                    this.pagination.pageSize=res.data.data.size
                    this.pagination.total=res.data.data.total
                    // console.log(res.data.data)
                    this.dataList=res.data.data.records

                })


            },

在这个输入框中没输入的话那就单纯只有按条件,输入的话就是按条件+分页的SQL语句

代码方面重要的基本就这样了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值