MP的开发流程-2

news2024/11/19 5:57:19

RESTful的实现等级

  • 0级:传统的RPC,基于SOAP的WS,调用的服务名,参数放在HTTP协议的body里面,同时必须以POST方式提交,问题在于你必须清楚的知道所有服务,子服务,及其参数的信息,并且需要知道各种服务的不同点
  • 1级:利用resource概念,把所有服务都抽取成resource概念,从body中提取到header里,这样做的好处就是如果你知道一个服务地址,你可能无需知道具体服务是什么,依照资源的惯例就访问到服务,比如查询id=1的书籍信息时使用路径/books/1
  • 2级:利用HTTP动词,HTTP定义了4种动词,GET获取服务器资源,POST在服务器上创建新资源,PUT更改服务器上资源,DELETE删除服务器上资源,任何操作都可以看成增删改查,所以利用标准的http verb加上resource(/book/1)就能准确地操作资源,当你不知道服务具体是什么的时候也可以轻易按照惯例访问到服务,然而服务供应商更改服务也需要遵循惯例,不会像RPC那样轻易更改服务接口
  • 3级:最高级别,HATEOS超媒体既应用状态引擎。这个意思是说,对于任何服务都存在很多子服务,你只需要知道第一个服务的入口,便可以依据服务返回结构的自描述性得到下一个服务的入口,这样在服务供应商修改服务的时候,不会影响到客户端的调用

在RESTful应用中需要和前端充分沟通,建议通信的数据规范

@Data
public class JsonResult implements Serializable{
    private int code;//自定义的响应状态码,不是http规范中的响应码,一般用于给前端更详细的信息
    private String message;//服务器端生成的响应提示信息
    private Boolean success;//可有可无,给前端一个简单的响应状态提示
    private Object data;//响应数据

    public static JsonResult success(String message, Object data){
        JsonResult result = new JsonResult();
        result.setMessage(message);
        result.setData(data);
        result.setCode(2000);
        result.setSuccess(true);
        return result;
    }
}

控制器类的定义

@RestController //@Controller + @ResponseBody
@RequestMapping("/catalogs")
public class CatalogController{
    @Autowired //@Resource
    private CatalogService catalogService;
    @GetMapping
    public JsonResult getAllCatalogs(){
        List<Catalog> catalogList = catalogService.list();
        return JsonResult.success("所有类目列表",catalogList);
    }
}

7、使用Postman进行测试

在mysql数据库中插入测试数据

insert into tbl_catalogs values
    (1,"计算机图书","计算机图书"),
    (2,"烹饪图书","做菜图谱"),
    (3,"音乐图书","教你音乐入门");

postman的用法

在这里插入图片描述

常见问题1:应用启动报错UnsatisfiedDependencyException,查看报错信息的详细提示

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.yan.mapper.CatalogMapper' available: expected at
least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatc
hingBeanFound(DefaultListableBeanFactory.java:1801) ~[spring-beans-
5.3.23.jar:5.3.23]
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDe
pendency(DefaultListableBeanFactory.java:1357) ~[spring-beans-5.3.23.jar:5.3.23]
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDepe
ndency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.23.jar:5.3.23]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcesso
r$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.j
ava:656) ~[spring-beans-5.3.23.jar:5.3.23]
... 39 common frames omitted

可以看到报错为com.yan.mapper.CatalogMapper没有注册,所以需要添加MyBatisPlus配置类或者在主类上添加配置

@MapperScan(basePackages = "com.ma.mapper") //注册自动扫描mapper接口,完成mapper接口的注册
@SpringBootConfiguration //用于声明当前类的一个配置类
public class MyBatisPlusConfig{
}

8、针对类目进行分页显示

分页操作可以利用MP中提供的分页插件实现,修改MP的配置类引入分页插件

@MapperScan(basePackages = "com.ma.mapper") //注册自动扫描mapper接口,完成mapper接口的注册
@SpringBootConfiguration //用于声明当前类的一个配置类
public class MyBatisPlusConfig{
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        mybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        intercetpor.addInterceptor(new PaginationInnerInterceptor(ObType.MYSQL);
        return interceptor;
    }
}

控制器类定义,这里需要传递分页参数。传递分页参数的值bean有多种写法

@Data //主要用于供前端实现分页导航
public class PageBean implements Serializable{
    private long pageNum; //当前页码值
    private long maxPage; //最大页面值
    private long rowsNum; // 总行数
    private long rowsPerPage = 15; //每页行数
//另外写法有:添加属性Object data存储查询结果集
}

控制器类

注意:这里新增业务方法listByPage目的在于后前使用redis缓存

@RestController //@Controller + @Responsebody
@RequestMapping("/catalogs")
public class CatalogController{
    @Autowird //@Resource
    private CatalogService catalogService;
    @GetMapping("show")
    public JsonResult getByPage(@RrquestParam(defaultValue = "1")Integer
page,@RequestParam(defaultValue="3") Integer size){
        PageBean pages = new PageBean();
        pages.setPageNum(page);
        pages.setRowsPerPage(size);
        List<Catalog> catalogList = catalogService.listByPage(pages);
        Map<String,Object> map = new HashMap<>();
        map.put("pages",pages);
        map.put("data",catalogList);
        return JsonResult.success("加载成功",map);
    }
}

修改业务方法的实现

实际上具体的分页实现很简单,就是在调用查询之前构建IPage类型的对象,然后调用Mapper接口中所提供的支持Page参数的方法即可

@Service
public class CatalogServiceImpl extends ServiceImpl<CatalogMapper, Catalog>
    implements CatalogService{
    
    @Override
    public List<Catalog> listByPage(PageBean pages){
        List<Catalog> res = new ArrayList<>();
        if(pages == null || pages.getRowsPerPage() < 1){
            //查询所有
            res = this.getBaseMapper().selectList(null);
        } else{
            //分页查询
            if(pages.getPageNum() < 1)
                pages.setPageNum(1);
            Page<Catalog> pageInfo = new Page<>(pages.getPageNum(),pages.getRowsPerPage());
            pageInfo = this.getBaseMapper().selectPage(pageInfo,null);
            res = pageInfo.getRecords();
            pages.setPageNum(pageInfo.getCurrent());
            pages.setRowsNum(pageInfo.getTotal());
            pages.setMaxPage(pageInfo.getPages());
        }
        return res;
    }
}

使用postman测试验证

生成的响应数据为JSON格式的字符串

{
    "code": 2000,
    "success": true,
    "message": null,
    "data": {
        "pages": {
            "pageNum": 1,
            "maxPage": 2,
            "rowsNum": 3,
            "rowsPerPage": 2
        },
        "data": [
            {
                "id": 1,
                "name": "计算机图书",
                "memo": "计算机图书"
            },
            {
                "id": 2,
                "name": "烹饪图书",
                "memo": "做菜的书"
            }
        ]
    }
}

9、针对类目信息发现一般很少修改,但是经常需要执行查询,例如添加商品等操作。比较适合使用redis缓存数据,通过浪费内存以减少数据库的查询此时,从而提供执行性能,应对更高的并发性需求redis缓存开发一般有2种方式,使用注解【推荐】和使用自定义编程实现。缓存可以添加在不同的层面上,一般针对controller缓存,多使用本地缓存Ehcache;如果针对业务层缓存,一般使用支持分布式的Redis;也可以在持久层添加缓存,例如开启的MyBatis的缓存

9.1、首先添加依赖

<!--业务层缓存-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</actifactId>
</dependency>

9.2、添加Redis序列化器和反序列化器的配置

@SpringBootConfiguration
public class MyRedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();//创建模板类对象
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();//创建String序列化类
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //指定使用jackson工具负责具体的序列化操作
        ObjectMapper om = new ObjectMapper(); //创建jackson的核心api的 ObjectMapper ,将bean,list,map,数组等等转成字符串
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 使用objectmapper设置bean的属性,修饰符
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);  //设置默认类型
        om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);  //设置将本地时间转成字符串
        jackson2JsonRedisSerializer.setObjectMapper(om);  //将核心api objectmapper设置给jackson
        template.setConnectionFactory(factory); // 通过工厂得到连接对象
        template.setKeySerializer(redisSerializer);  //设置key序列化方式: 转成字符串
        template.setValueSerializer(jackson2JsonRedisSerializer); // 设置value序列化: 字符串
        template.setHashValueSerializer(jackson2JsonRedisSerializer); // value hashmap序列化
        return template;
    }
}

9.3、添加Redis服务器相关配置

spring:
    redis:
        host: localhost
        port: 6379
        lettuce:
            pool:
                max-active: 8
                min-idle: 3

9.4、通过spring框架提供的模板类RedisTemplate调用API操作Redis数据库

在使用redis缓存之前应该充分沟通,定义一个key的标准,或者查询公司旧有标准,注意不能随机起名

@Service
public class CatalogServiceImpl extends ServiceImpl<CatalogMapper, Catalog>
    implements CatalogService{
    @Autowired
    private RedisTemplate redisTemplate
    private ThreadLocalRandom random = ThreadLocalRandom.current();

    @Override
    public List<Catalog> listByPage(PageBean pages){
        List<Catalog> res = new ArrayList<>();
        if(pages == null || pages.getRowsPerPage() < 1){
            //查询所有
            if(redisTemplate.haskey("catalog::all")){
                //如果在具体开发中比较倾向与使用常量的方式
                Object obj = redisTemplate.opsForValue().get("catalog::all");
                if(obj != null && obj instanceof List)
                    res = (List<Catalog>) obj;
            } else {
                res = this.getBaseMapper().selectList(null);
                if(res != null && res.size() > 0){
                    //为了避免雪崩问题,所以生命周期引入随机数
                    int kk = 100 + random.nextInt(100);
                    redisTemplate.opsForValue().set("catalog:: all",res,
Duration.ofSeconds(kk));
                }
            }
        } else {
            //分页查询,实际上具体的应用中不一定针对分页数据进行缓存 catalog::page::size
            if(pages.getPageNum() < 1)
                pages.setPageNum(1);
            String key = "catalog::" + pages.getPageNum() + "::" +
pages.getRowsPerPage();
            if(this.redisTemplate.hasKey(key)){
                Object obj = redisTemplate.opsForValue().get(key);
                if(obj!=null && obj intanceof List)
                    res = (List < Catalog>) obj;
                if(this.redisTemplate.hasKey(key+"::page")){
                    obj = redisTemplate.opsForValue.get(key + "::page");
                    if(obj != null && obj instance PageBean){
                        PageBean tmp = (PageBean) obj;
                        BeanUtils.copyProPerties(tmp,pages);
                    }
                }
            }
            if(res == null || res.size() < 1){
                Page<Catalog> pageInfo = new Page<>(pages.getPageNUm(),
pages.getRowsPerPage());
                pageInfo = this.getBaseMapper().selectPage(pageInfo,null);
                res = pageInfo.getRecords();
                pages.setPageNum(pageInfo.getCurrent());
                pages.setRowsNum(pageInfo.getTotal());
                pages.setMaxPage(pageInfo.getPages());
                int kk = 100 + random.nextInt(100);
                redisTemplate.opsForValue().set(key,res,Duration.ofSeconds(kk));
            }
        }
        return res;
    }
}

9.5、使用postman测试,可以在控制台上查看是否有对应的SQL语句输出以判断缓存是否生效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot环境标识设置及nacos匹配配置

本地环境标识设置 本地父类maven配置 可以看到相关的分类&#xff0c;设置环境标识主要需要用到profiles; <profiles><profile><id>dev</id><properties><!-- 环境标识&#xff0c;需要与配置文件的名称相对应 --><profiles.active&…

AX7A200教程(8): HDMI输入和输出显示1080p视频

文章目录 本章节主要将hdmi输入的1080p视频通过ddr3缓存&#xff0c;然后通过hdmi输出口输出到显示屏上显示 一&#xff0c; 突发读写命令 设置读写突发长度为64 //parameter defineparameter WRITE_LENGTH 64;parameter READ_LENGTH 64;parameter IDLE 3d0; …

SSM面试题-Spring容器的启动流程

解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后&#xff0c;将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…

fastadmin采坑之固定表格某一列

// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: id,sortName: id,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: id, title: __(Id)},{field: proposal_title, title: __(Proposal_title), opera…

Modbus Poll 软件----下载和安装

Modbus Poll 下载 modbus tools 官网地址&#xff1a;https://www.modbustools.com/ 步骤1 点击进入官网&#xff0c;然后点击 DOWNLOAD&#xff0c;进入下载界面。 步骤2 在下载界面&#xff0c;点击 Download 64bit &#xff0c;下载 Modbus Poll。 步骤3 下载完成 Mo…

如何生成丰富的啸叫样本?

前段时间有个公众号的朋友问我如何生成丰富的啸叫类型&#xff0c;当时回答比较简单&#xff0c;只是把啸叫产生的条件说了一下&#xff0c;后来在写AI降噪的N种数据扩增方法时候也简单提了一下使用冲激响应(Impluse Respose, IR)和增益产生啸叫&#xff0c;今天我们把这个坑填…

RabbitMQ 教程 | 第3章 客户端开发向导

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

第1章 JavaScript简史

JavaScript的起源 JavaScript是Netscape公司与Sun公司合作开发的在JavaScript诞生之前游览器就是显示超文本文档的简单的软件&#xff0c;JavaScript为此增加了交互行为ECMAScript是JavaScript的标准化&#xff0c;本质上是同一个语言JavaScript是一门脚本语言通常只能运行在游…

VCS ICO - Intelligent Coverage Optimization

ico是vcs提供的用于优化覆盖率的feature&#xff1b;一般用户通过dist solver bofore等约束了变量的随机概率&#xff0c;而ico会在用户约束的基础上&#xff0c;做一些自动“修正”&#xff0c;以此来优化随机激励&#xff0c;提高随机多样性&#xff0c;加速覆盖率收敛&#…

【腾讯云 Cloud Studio 实战训练营】通过云IDE构建Web3项目

文章目录 背景一、 前言二、 Cloud Studio 主要功能三、Cloud Studio 实验前期准备3.1. 注册平台 四、构建Web3项目项目中技术栈 五、其他功能演示六、常见问题及注意事项七、总结八、相关链接 ​ Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(12)-Fiddler设置IOS手机抓包,你知多少???

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求&#xff0c;比如 iPhone、iPad 和 MacBook 等苹…

每日一题——只出现一次的数字

只出现一次的数字 题目链接 思路 要求为线性时间复杂度&#xff0c;即时间复杂度为O(n)&#xff0c;那么我们就不能用简单的两层循环来解决问题 要求只能使用常量额外空间&#xff0c;即空间复杂度为O(1)&#xff0c;那么我们就不能额外开辟一个数组来记录每个元素出现的次数…

Cpp学习——通过日期类来了解Cpp中的运算符重载

目录 一&#xff0c;日期类 二&#xff0c;运算符重载 运算符重载1(比较&#xff09; 1.< 2. 复用 3.> 4.! 5.< 6.> 运算符重载2(日期加减&#xff09; 0.准备条件------计算每月的日期函数 1. 2. 3.- 4.- 5.前置 6.后置 7前置-- 6.后置-- 7.计…

「BLIP 微调指南」以 Image-Text Captioning 任务为例

前言&#xff1a;近日需要用到 BLIP 微调下游任务&#xff0c;搜索发觉如今并无 BLIP 微调教程&#xff0c;下面就以 Image-Text Captioning 任务为例&#xff0c;演示如何完成 BLIP 模型在自己数据集上的微调。 目录 1. BLIP 介绍2. 关键代码定位3. 关键参数赋值4. 模型定义&a…

Scratch 教程 之 如何四舍五入保留一个小数到指定的数位

有些时候&#xff0c;我们需要四舍五入一个多位小数到指定的位&#xff0c;但scratch并没有这个积木&#xff0c;怎么做呢&#xff1f;我来教你&#xff5e; 我们创建一个函数&#xff0c;需要时调用就行了&#xff5e; 如图&#xff0c;创建一个带参函数&#xff0c;勾选"…

《GreenPlum系列-部署维护》GreenPlum数据库Standby故障处理

一、Standby故障 1.检查监控中心数据库状态 2.查看master节点数据库状态 su - gpadmin gpstate -f二、重启数据库 1.快速关闭数据库 [gpadminmdw pg_log]$ gpstop -M fast ... Continue with Greenplum instance shutdown Yy|Nn (defaultN): > y ...2.开启数据库 [gpad…

[SSM]Spring对事务的支持

目录 十六、Spring对事务的支持 16.1事务概述 16.2引入事务场景 16.3Spring对事务的支持 Spring实现事务的两种方式 Spring事务管理API 声明式事务之注解实现方式 事务属性 事务的全注解式开发 声明式事务之XML实现方式 十六、Spring对事务的支持 16.1事务概述 什么是…

stm32 mpu6050 cubemx DMP法读取角度

文章目录 前言一、相关文件二、cubemx配置三、代码变量初始化主循环 总结 前言 文件 记录使用dmp库来读取mpu6050的角度。 这是参考文件 参考1–主要参考 github参考 参考2 参考三 一、相关文件 相关文件在这里下载&#xff08;未填&#xff0c;不过可以在上面的git中下载&a…

(树) 剑指 Offer 28. 对称的二叉树 ——【Leetcode每日一题】

❓ 剑指 Offer 28. 对称的二叉树 难度&#xff1a;简单 请实现一个函数&#xff0c;用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样&#xff0c;那么它是对称的。 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1/ \2 2/ \ / \3 4 4 3但是下面这个…

在Python中导入gurobipy模块显示ModuleNotFoundError: No module named ‘gurobipy‘的解决办法

笔者在学习用pythonAnacondagurobi求解优化问题时遇到了这个问题&#xff0c;看了很多帖子的方法都没有解决&#xff0c;所以这里分享一下自己的解决办法。 首先找到自己用的Anaconda3所在位置&#xff0c;这里不再赘述。 下拉文件夹找到envs&#xff0c;双击PythonProject&…