第七课(3)—— swagger、RESTful api_嘘嘘喵

嘘嘘喵 社区会员 2022-01-21 20:50:55

Swagger

1. 定位相关代码

application-dev.yml 文件中,有这么一段 swagger 相关的代码

#是否开启 swagger-ui
swagger:
  enabled: true
  title: 管理后台API
  serverUrl: http://127.0.0.1:8000
  version: 2.2

在 IDEA 中,用查找用法搜索 swagger ,可以找到一个叫 SecurityConfig 的类,类中有这么一段 swagger 相关的代码:

                // swagger 文档
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()
                .antMatchers("/v2/api-docs-ext").permitAll()
                //.antMatchers("/api/wxmp/**").permitAll()

2. 访问 swagger 文档

按照代码的设置,先启动项目,再访问 localhost:8000/swagger-ui.html,可成功访问,效果如图:

image-20220117204243712

3. 更改 redis 相关设置

AuthController 类中的相关代码编辑为如下:

// 保存
redisUtils.set(uuid, result, expiration, TimeUnit.HOURS);

这样,验证码的失效时间就变为了 1 小时(原为 1 分钟)

4. 获取 token

在 swagger 页面,系统:系统授权接口 -> try it out -> excute

4.1 验证码源码

获取到的响应如下:

{
  "uuid": "code-key050d4698495246588e6f46c50a87bf2c",
  "img": "data:image/png;base64,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"

这其中,uuid 后面的字符串是 uuid,img 后面的字符串是验证码图片的 base64 码,需要转化成图像。

4.2 验证码图像

专门写一个 html 文件,用于将 base64 格式的图片编码转化为图像吗,代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>我的前端练习</title>
  </head>
  <body>
    <div>我的前端练习--二进制流图片及RSA加密</div>
    <img src=""></img>
  </body>
</html>

其中,src 是要转为图片的 base64 码,将刚刚的base64 码填进去,再打开 HTML 页面。

可得到验证码图片:

image-20220118171820755

4.3 获取 RSA 加密后的密码

在刚刚的 html 文件中,添加 RSA 加密的相关脚本:

<!--引入jsencrypt.js-->
<script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script>
<script type="text/javascript">
//公钥
var PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' +
  '2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ=='
//私钥
var PRIVATE_KEY = 'data:image/png;base64,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'

//使用公钥加密
var encrypt = new JSEncrypt();
//encrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----'+PRIVATE_KEY+'-----END RSA PRIVATE KEY-----');
encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');

var encrypted = encrypt.encrypt("123456");
console.log('加密前数据:%o', "");
console.log('加密后数据:%o', encrypted);
//使用私钥解密
//var decrypt = new JSEncrypt();
//decrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
//decrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----'+PRIVATE_KEY+'-----END RSA PRIVATE KEY-----');
//var uncrypted = decrypt.decrypt(encrypted);
//console.log('解密后数据:%o', uncrypted);
</script>

添加后,在加密前数据后面填写原本的密码。完成后启动浏览器,在控制台可以获取 RSA 加密后的密码。

image-20220118172631897

4.4 登录

打开登录接口,然后 try it out:

image-20220118172248037

在 addUser 中,把后面的内容填上,如下:

{
  "code": "4",
  "password": "dqzr75SJUPUL0MERjBerOHRsRMJRaT27mNIwQL2igJ2G/EB1VdJZ83gesfmwHEBfGGlC51b8LuT6qbXpm81P8w==",
  "username": "admin",
  "uuid": "code-key050d4698495246588e6f46c50a87bf2c"
}

填写完毕后点击 excute,即可获得一个响应,内容如下:

{
  "user": {
    "id": 1,
    "username": "admin",
    "nickName": "管理员",
    "sex": "男",
    "avatar": null,
    "email": "yshop@qq.com",
    "phone": "18888888888",
    "dept": "研发部",
    "job": "全栈开发2",
    "enabled": true,
    "createTime": 1534986716000,
    "roles": [
      "YXUSER_SELECT",
      "YXSTOREORDER_SELECT",
      "YXSTORECOMBINATION_SELECT",
      "YXSTORESECKILL_SELECT",
      "YXSYSTEMUSERLEVEL_SELECT",
      "YXSTORECATEGORY_SELECT",
      "admin",
      "YXSTOREBARGAIN_SELECT",
      "YXSTOREPRODUCT_EDIT",
      "YXSTORECOUPONISSUE_SELECT",
      "storage:list",
      "YXSTOREPRODUCT_CREATE",
      "YXSTOREPRODUCTREPLY_SELECT",
      "YXEXPRESS_SELECT",
      "YXSTOREPRODUCT_SELECT",
      "admin,menu:list,roles:list",
      "YXSYSTEMUSERTASK_SELECT",
      "timing:list",
      "YXSTOREPRODUCT_DELETE",
      "YXSTORECOUPON_SELECT"
    ]
  },
  "token": "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImF1dGgiOiJZWFVTRVJfU0VMRUNULFlYU1RPUkVPUkRFUl9TRUxFQ1QsWVhTVE9SRUNPTUJJTkFUSU9OX1NFTEVDVCxZWFNUT1JFU0VDS0lMTF9TRUxFQ1QsWVhTWVNURU1VU0VSTEVWRUxfU0VMRUNULFlYU1RPUkVDQVRFR09SWV9TRUxFQ1QsYWRtaW4sWVhTVE9SRUJBUkdBSU5fU0VMRUNULFlYU1RPUkVQUk9EVUNUX0VESVQsWVhTVE9SRUNPVVBPTklTU1VFX1NFTEVDVCxzdG9yYWdlOmxpc3QsWVhTVE9SRVBST0RVQ1RfQ1JFQVRFLFlYU1RPUkVQUk9EVUNUUkVQTFlfU0VMRUNULFlYRVhQUkVTU19TRUxFQ1QsWVhTVE9SRVBST0RVQ1RfU0VMRUNULGFkbWluLG1lbnU6bGlzdCxyb2xlczpsaXN0LFlYU1lTVEVNVVNFUlRBU0tfU0VMRUNULHRpbWluZzpsaXN0LFlYU1RPUkVQUk9EVUNUX0RFTEVURSxZWFNUT1JFQ09VUE9OX1NFTEVDVCIsImV4cCI6MTY0MjUxMjQ2OH0.TxPFNiFuQdETy4t5Ax5-j_9ZuB2TEn3vYinZOUgI3B7jHvfXotxETLqUJOB78o6n3Z1UrzOvYtuT1iTxn2mIxw"
}

说明登录成功,并且成功拿到了 token。

4.5 使用 token 访问其他接口

拿到 token 之后,就可以访问其他接口了,以获取用户信息为例。

进入 系统:系统授权接口,点击 try it out

image-20220118173133196

Authorization 栏内填入刚刚的 token:

image-20220118174403275

点击 excute,即可获得用户信息:

image-20220118174616190

RESTful api

一、初始化数据库

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 80015
Source Host           : 127.0.0.1:3306
Source Database       : lab_mall_db

Target Server Type    : MYSQL
Target Server Version : 80015
File Encoding         : 65001

Date: 2022-01-18 20:26:43
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for myinfo
-- ----------------------------
DROP TABLE IF EXISTS `xxminfo`;
CREATE TABLE `xxminfo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '我的ID',
  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '我的姓名',
  `remark` varchar(2000) DEFAULT NULL COMMENT '我的备注',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '最后修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='我的信息';

-- ----------------------------
-- Records of myinfo
-- ----------------------------
INSERT INTO `xxminfo` VALUES ('1', '嘘嘘喵', '备注1', '2022年1月19日15:37:52', '2022年1月19日15:37:55');
INSERT INTO `xxminfo` VALUES ('2', '嘘嘘喵22', '备注222', '2022年1月19日15:38:02', '2022年1月19日15:37:59');

二、创建项目

项目直接沿用前面的项目,在 yshop-system 模块,/src/main/java/co.yixiang/modules 下创建文件夹 xxm ,以用作这次练习。

创建好三个文件夹:

image-20220119164154200

domain :用于存放实体类

三、编写内容

1. 实体类

domain 文件夹下创建一个类 XxmInfo ,内容如下:

package co.yixiang.modules.xxm.domain;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.security.Timestamp;

/**
 * @author: xxm
 * @Date: 2022/1/19 16:49
 * xxminfo 表对应的实体类
 */

@Data
@TableName("xxminfo")
public class XxmInfo implements Serializable {

    /**
     * ID
     */
    @TableId
    private long id;

    /**
     * 姓名
     */
    @NotBlank(message = "姓名不能为空")
    private String name;

    /**
     * 备注
     */
    private String remark;

    /**
     * 创建日期(自动填充)
     */
    @TableField(fill = FieldFill.INSERT)
    private Timestamp createTime;

    /**
     * 最后修改日期(自动填充)
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Timestamp updateTime;

}

2. Dto 类

dto 文件夹中创建一个新类:XxmInfoDto

答:

package co.yixiang.modules.xxm.service.dto;

import java.security.Timestamp;

/**
 * @author: xxm
 * @Date: 2022/1/20 10:56
 * Dto类,一般用于与前端交互
 */
public class XxmInfoDto {

    /**
     * ID
     */
    private long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 备注
     */
    private String remark;

    /**
     * 创建日期(自动填充)
     */
    private Timestamp createTime;

    /**
     * 最后修改日期(自动填充)
     */
    private Timestamp updateTime;


}

3. Controller类

rest 文件夹下创建类 XxmInfoCrontroller

内容如下:

package co.yixiang.modules.xxm.rest;

import co.yixiang.logging.aop.log.Log;
import co.yixiang.modules.xxm.service.XxmInfoService;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author: xxm
 * @Date: 2022/1/19 18:52
 * xxminfo 接口
 */
@Api(tags = "xxm:用户信息")
@RestController
@RequestMapping("/api/xxminfo")
public class XxmInfoController {

   private final XxmInfoService xxmInfoService;

   public XxmInfoController(XxmInfoService xxmInfoService){
        this.xxmInfoService = xxmInfoService;
   }

    /**
     * 查询用户信息
     */
    @Log("查询用户信息")
    @ApiOperation("查询用户信息")
    @GetMapping(value = "/all")
    @PreAuthorize("@el.check('admin','xxminfo:list')")
    public ResponseEntity<Object> all() {
        return new ResponseEntity<>(xxmInfoService.queryAll(new XxmInfoQueryCriteria()), HttpStatus.OK);
    }

}

4. 查询条件类

service 文件夹下创建 dto 文件夹,并创建 XxmInfoQueryCriteria 类。

代码如下:

package co.yixiang.modules.xxm.service.dto;

import co.yixiang.annotation.Query;
import lombok.Data;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:05
 * 查询条件
 */

@Data
public class XxmInfoQueryCriteria {

    @Query
    private String name;

}

5. mapper 接口

service 文件夹下创建 mapper 文件夹,并创建 XxmInfoMapper 类。

代码如下:

package co.yixiang.modules.xxm.service.mapper;

import co.yixiang.common.mapper.CoreMapper;
import co.yixiang.modules.xxm.domain.XxmInfo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:28
 * xxminfo 的 mapper 接口
 */

@Repository
@Mapper
public interface XxmInfoMapper extends CoreMapper<XxmInfo> {

}

6. service 接口

创建 XxmInfoService 类,作为接口。

代码如下:

package co.yixiang.modules.xxm.service;

import co.yixiang.common.service.BaseService;
import co.yixiang.modules.my.service.dto.MyInfoQueryCriteria;

import co.yixiang.modules.xxm.domain.XxmInfo;
import co.yixiang.modules.xxm.service.dto.XxmInfoDto;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Map;

/**
 * @author: xxm
 * @Date: 2022/1/19 20:08
 * xxminfo 的 service 接口
 */
public interface XxmInfoService extends BaseService<XxmInfo> {

    List<XxmInfoDto> queryAll(XxmInfoQueryCriteria criteria);
}

7. service 实现类

service 文件夹下创建 dto 文件夹,并创建 XxmInfoServiceImpl 类。

代码如下:

package co.yixiang.modules.xxm.service.impl;

import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.modules.xxm.domain.XxmInfo;
import co.yixiang.modules.xxm.service.XxmInfoService;
import co.yixiang.modules.xxm.service.dto.XxmInfoDto;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import co.yixiang.modules.xxm.service.mapper.XxmInfoMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:11
 */

@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class XxmInfoServiceImpl extends BaseServiceImpl<XxmInfoMapper, XxmInfo> implements XxmInfoService {

    private final IGenerator generator;

//    @Override
//    public Map<String, Object> queryAll(MyInfoQueryCriteria criteria, Pageable pageable) {
//        getPage(pageable);
//        PageInfo page = new PageInfo(queryAll(criteria));
//        Map<String, Object> map = new LinkedHashMap<>(2);
//        map.put("content", generator.convert(page.getList(), XxmInfoDto.class));
//        map.put("totalElements", page.getTotal());
//        return map;
//    }

    @Override
    public List<XxmInfoDto> queryAll(XxmInfoQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(XxmInfoDto.class, criteria));
    }
}

8. 测试

在 swagger 中 ,访问 xxm:用户信息接口,执行后可以得到响应:

image-20220121171201759

四、 完善项目

按照第三章中的内容,给项目添加增、删、改的功能。

过程忽略,这边直接放上编辑过后的代码:

1. 实体类

package co.yixiang.modules.xxm.domain;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.security.Timestamp;
import java.util.Date;

/**
 * @author: xxm
 * @Date: 2022/1/19 16:49
 * xxminfo 表对应的实体类
 */

@Data
@TableName("xxminfo")
public class XxmInfo implements Serializable {

    /**
     * ID
     */
    @TableId
    private Long id;

    /**
     * 姓名
     */
    @NotBlank(message = "姓名不能为空")
    private String name;

    /**
     * 备注
     */
    private String remark;

    /**
     * 创建日期(自动填充)
     */
    @TableField(fill= FieldFill.INSERT)
    private Date createTime;

    /**
     * 最后修改日期(自动填充)
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

}

2. Dto 类

package co.yixiang.modules.xxm.service.dto;

import java.security.Timestamp;

/**
 * @author: xxm
 * @Date: 2022/1/20 10:56
 * Dto类,一般用于与前端交互
 */
public class XxmInfoDto {

    /**
     * ID
     */
    private long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 备注
     */
    private String remark;

    /**
     * 创建日期(自动填充)
     */
    private Timestamp createTime;

    /**
     * 最后修改日期(自动填充)
     */
    private Timestamp updateTime;


}

3. Controller 类

package co.yixiang.modules.xxm.rest;

import co.yixiang.exception.BadRequestException;
import co.yixiang.logging.aop.log.Log;
import co.yixiang.modules.xxm.domain.XxmInfo;
import co.yixiang.modules.xxm.service.XxmInfoService;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author: xxm
 * @Date: 2022/1/19 18:52
 * xxminfo 接口
 */
@Api(tags = "xxm:用户信息")
@RestController
@RequestMapping("/api/xxminfo")
public class XxmInfoController {

   private final XxmInfoService xxmInfoService;

   public static final String ENTITY_NAME = "xxminfo";

   public XxmInfoController(XxmInfoService xxmInfoService){
        this.xxmInfoService = xxmInfoService;
   }

    /**
     * 查询用户信息
     */
    @Log("查询全部用户信息")
    @ApiOperation("查询全部用户信息")
    @GetMapping(value = "/all")
    @PreAuthorize("@el.check('admin','xxminfo:list')")
    public ResponseEntity<Object> all() {
        return new ResponseEntity<>(xxmInfoService.queryAll(new XxmInfoQueryCriteria()), HttpStatus.OK);
    }


//    @Log("查询字典")
//    @ApiOperation("查询字典")
//    @GetMapping
//    @PreAuthorize("@el.check('admin','dict:list')")
//    public ResponseEntity<Object> getDicts(DictQueryCriteria resources, Pageable pageable) {
//        return new ResponseEntity<>(dictService.queryAll(resources, pageable), HttpStatus.OK);
//    }
//

    @Log("新增用户")
    @ApiOperation("新增用户")
    @PostMapping
    @PreAuthorize("@el.check('admin','xxminfo:add')")
    public ResponseEntity<Object> create(@Validated @RequestBody XxmInfo resources) {
        if (resources.getId() != null) {
            throw new BadRequestException("A new " + ENTITY_NAME + " cannot already have an ID");
        }
        return new ResponseEntity<>(xxmInfoService.save(resources), HttpStatus.CREATED);
    }

    @Log("修改用户信息")
    @ApiOperation("修改用户信息")
    @PutMapping
    @PreAuthorize("@el.check('admin','xxminfo:edit')")
    public ResponseEntity<Object> update(@Validated @RequestBody XxmInfo resources) {
        xxmInfoService.saveOrUpdate(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @Log("删除用户")
    @ApiOperation("删除用户")
    @DeleteMapping(value = "/{id}")
    @PreAuthorize("@el.check('admin','xxminfo:del')")
    public ResponseEntity<Object> delete(@PathVariable Long id) {
        xxmInfoService.removeById(id);
        return new ResponseEntity<>(HttpStatus.OK);

    }
}

4. 查询条件类

package co.yixiang.modules.xxm.service.dto;

import co.yixiang.annotation.Query;
import lombok.Data;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:05
 * 查询条件
 */

@Data
public class XxmInfoQueryCriteria {

    @Query
    private String name;

}

5. mapper 接口

package co.yixiang.modules.xxm.service.mapper;

import co.yixiang.common.mapper.CoreMapper;
import co.yixiang.modules.xxm.domain.XxmInfo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:28
 * xxminfo 的 mapper 接口
 */

@Repository
@Mapper
public interface XxmInfoMapper extends CoreMapper<XxmInfo> {

}

6. service 接口

package co.yixiang.modules.xxm.service;

import co.yixiang.common.service.BaseService;
import co.yixiang.modules.my.service.dto.MyInfoQueryCriteria;

import co.yixiang.modules.xxm.domain.XxmInfo;
import co.yixiang.modules.xxm.service.dto.XxmInfoDto;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Map;

/**
 * @author: xxm
 * @Date: 2022/1/19 20:08
 * xxminfo 的 service 接口
 */
public interface XxmInfoService extends BaseService<XxmInfo> {
//    /**
//     * 查询数据分页
//     *
//     * @param criteria 条件
//     * @param pageable 分页参数
//     * @return Map<String, Object>
//     */
//    Map<String, Object> queryAll(MyInfoQueryCriteria criteria, Pageable pageable);


    /**
     * 查询
     *
     * @param criteria
     * @return
     */
    List<XxmInfoDto> queryAll(XxmInfoQueryCriteria criteria);

    /**
     * 新增用户
     *
     * @param xxmInfo
     */
    XxmInfoDto create(XxmInfo xxmInfo);


    /**
     * 编辑用户信息
     *
     * @param xxmInfo
     */
    void update(XxmInfo xxmInfo);

//    /**
//     * 删除用户信息
//     *
//     * @param xxmInfo
//     */
//    void delete(XxmInfo xxmInfo);

}

7. service 实现类

package co.yixiang.modules.xxm.service.impl;

import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.exception.EntityExistException;
import co.yixiang.modules.xxm.domain.XxmInfo;
import co.yixiang.modules.xxm.service.XxmInfoService;
import co.yixiang.modules.xxm.service.dto.XxmInfoDto;
import co.yixiang.modules.xxm.service.dto.XxmInfoQueryCriteria;
import co.yixiang.modules.xxm.service.mapper.XxmInfoMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author: xxm
 * @Date: 2022/1/19 21:11
 */

@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class XxmInfoServiceImpl extends BaseServiceImpl<XxmInfoMapper, XxmInfo> implements XxmInfoService {

    private final IGenerator generator;

//    @Override
//    public Map<String, Object> queryAll(MyInfoQueryCriteria criteria, Pageable pageable) {
//        getPage(pageable);
//        PageInfo page = new PageInfo(queryAll(criteria));
//        Map<String, Object> map = new LinkedHashMap<>(2);
//        map.put("content", generator.convert(page.getList(), XxmInfoDto.class));
//        map.put("totalElements", page.getTotal());
//        return map;
//    }

    /**
     * 查询所有用户信息
     *
     * @param criteria
     * @return
     */
    @Override
    public List<XxmInfoDto> queryAll(XxmInfoQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(XxmInfoDto.class, criteria));
    }

    /**
     * 增加用户
     *
     * @param resources
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public XxmInfoDto create(XxmInfo resources) {
        if (this.getOne(new QueryWrapper<XxmInfo>().lambda().eq(XxmInfo::getName, resources.getName())) != null) {
            throw new EntityExistException(XxmInfo.class, "username", resources.getName());
        }

        this.save(resources);

        return generator.convert(resources, XxmInfoDto.class);

    }

    /**
     * 修改用户信息
     *
     * @param resources
     */
    @Override
    public void update(XxmInfo resources) {
        XxmInfo xxm1 = this.getById(resources.getId());

        XxmInfo xxm2 = this.getOne(new QueryWrapper<XxmInfo>().lambda().eq(XxmInfo::getName, resources.getName()));

        if (xxm2 != null && !xxm2.getId().equals(xxm1.getId())) {
            throw new EntityExistException(XxmInfo.class, "username", resources.getName());
        }
        xxm2 = this.getOne(new QueryWrapper<XxmInfo>().lambda().eq(XxmInfo::getName, resources.getName()));
        if (xxm2 != null && xxm2.getId().equals(xxm1.getId())) {
            throw new EntityExistException(XxmInfo.class, "username", resources.getName());
        }
        xxm1.setName(resources.getName());
        xxm1.setRemark(resources.getRemark());
        this.saveOrUpdate(xxm1);

    }

//
//    /**
//     * 删除用户
//     * @param xxmInfo
//     */
//    @Override
//    public void delete(XxmInfo xxmInfo) {
//
//    }
}
...全文
13528 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

110

社区成员

发帖
与我相关
我的任务
社区描述
训练、训练、训练!
其他 其他
社区管理员
  • 实训001
  • 非鱼up
  • andy421
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

自律训练,自信挑战!

试试用AI创作助手写篇文章吧