MP的开发流程-2

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语句输出以判断缓存是否生效

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FileZilla Server同时共享多个目录(手把手教你使用FileZilla Server同时设置多个目录)

网上的基本全是一句话带过怎么共享多个目录&#xff0c;没图很烦&#xff0c;所以我自己就写一个过程 目录 1、创建ftp用户并设置密码 1.1、进入用户管理 1.2、新建用户 1.3、设置密码 2、添加共享的目录 2.1、选择用户添加目录 2.2、给予用户访问权限 2.2.1、客户端访…

长相思·罚站墙Vue

优化前 看效果图 Vue长相思 刚学Vue&#xff0c;正好在追剧&#xff0c;看到这个小案例觉得挺好玩的&#xff0c;第一天学&#xff0c;代码太简陋了 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta…

windows环境下安装elasticsearch、kibana

通过本文可以快速在windows系统上安装elasticsearch、kibana环境。 当你用Integer类型的时候&#xff0c;要非常小心&#xff0c;因为100等于100、但是200不等于200&#xff0c;当然&#xff0c;如果你会一点小花招&#xff0c;也可以让100不等于100、让200等于200。(运算符比较…

全球十大知名看黄金即时行情的软件名单(综合榜单)

在当今的数字化时代&#xff0c;黄金投资已成为一种受欢迎的投资方式。为了获取即时的黄金行情信息&#xff0c;许多投资者开始使用黄金即时行情软件。然而&#xff0c;选择一款合适的软件并不是一件容易的事情。那么&#xff0c;如何选适合自己需求的软件呢&#xff1f;首先&a…

LeetCode344.反转字符串

344.反转字符串 题目描述 解题思路 这是字符串专题的第一题 在之前反转链表的题目中&#xff0c;我们使用了双指针法来进行反转链表 这道题同样的&#xff0c;也使用双指针&#xff0c;对于字符串的反转&#xff0c;比链表更为简单 因为字符串本质上是一种数组&#xff0c…

【嵌入式学习笔记】嵌入式入门5——窗口看门狗WWDG

1.WWDG简介 WWDG的全称&#xff1a;Window watchdog&#xff0c;即窗口看门狗WWDG的本质&#xff1a;能产生系统复位信号和提前唤醒中断的计数器WWDG的特性&#xff1a;递减的计数器&#xff0c;当递减计数器值从 0x40减到0x3F时复位&#xff08;即T6位跳变到0&#xff09;&am…

性能优化-react路由懒加载和组件懒加载

背景 随着项目越来越大&#xff0c;打包后的包体积也越来越大&#xff0c;严重影响了首屏加载速度&#xff0c;需要对路由和组件做懒加载处理 主要用到了react中的lazy和Suspense。 废话不多说&#xff0c;直接上干货 路由懒加载 核心代码 import React, { lazy, Suspens…

三款AI写作宝介绍,教你玩转AI写作

AI写作宝是一款利用人工智能技术自动生成文章的工具。它采用先进的自然语言处理算法&#xff0c;可以在短时间内生成高质量的文章。与传统的写作方式相比&#xff0c;AI写作宝有着更快的速度、更高的准确性和更低的成本&#xff0c;成为了许多人工智能爱好者和写作从业者的首选…

写字楼门禁如何管理?最最新方法来了!

在现代社会&#xff0c;随着城市化和商务发展的蓬勃推进&#xff0c;大厦写字楼作为繁忙的商业中心和办公场所&#xff0c;其安全管理和员工考勤变得尤为重要。为了应对这一挑战&#xff0c;人脸门禁考勤机应运而生&#xff0c;成为大厦写字楼的安全保障和工时管理的关键工具。…

【数模】聚类模型

分类和聚类 分类&#xff1a;最终类别是确认的&#xff0c;把各样本分到已有的类别中聚类&#xff1a;最终类别是未知的&#xff0c;把所有样本划分出最终类别 一、K-means聚类算法 1.1 K-means算法了解 算法流程&#xff08;推荐使用流程图&#xff1a;更简洁&#xff0c;且…

Mybatis引出的一系列问题-JDBC 的探究

1 引入对JDBC的理解-1 一般来说&#xff0c;Java应用程序访问数据库的过程是&#xff1a; 装载数据库驱动程序&#xff1b;通过jdbc建立数据库连接&#xff1b;访问数据库&#xff0c;执行sql语句&#xff1b;断开数据库连接。 Public void FindAllUsers(){//1、装载sqlserve…

synchronized总结

目录 一、synchronized的特性 1.1 原子性 1.2 可见性 1.3 有序性 1.4 可重入性 二、synchronized的使用 2.1 修饰普通方法 2.2 修饰静态方法 2.3 修饰代码块 三、synchronized的锁机制 3.1 偏向锁 3.2 轻量级锁 3.3 重量级锁 一、synchronized的特性 1.1 原子性 原子性是指一…

Eclipse进行debug

目录 基本步骤三种执行方式 -- 键盘快捷键variables面板移除debug过的项目通过eclipse调用具有软件界面的项目进行debug各个variable颜色具有的意义 基本步骤 点击eclipse右上角debug按钮 调出debug面板 点击小蜘蛛图标&#xff08;不是点绿色三角的Run&#xff09; 此时会进…

华为流程体系:流程架构「OES方法」

目录 内容简介 OES方法 端到端的流程 专栏列表 CSDN学院 作者简介 内容简介 今天继续来谈谈华为流程体系中的流程架构。 在前期的内容已经介绍过 POS 流程架构的方法。 这里就先回顾一下 POS 方法的相关内容&#xff1a; 关于 POS&#xff0c;大家可以参看上面的这张图…

实现天气预报走势图

实现效果&#xff1a; 这里我用的天气接口是网上开源的&#xff0c;可以自己找一下。 稍微简单封装了一下axiso以及接口 封装的axios&#xff1a; // import { useUserStore } from /stores/user import axios from axios import router from /router import { ElMessage } f…

Nginx 高性能内存池 ----【学习笔记】

跟着这篇文章学习&#xff1a; c代码实现一个高性能内存池&#xff08;超详细版本&#xff09;_c 内存池库_linux大本营的博客-CSDN博客https://blog.csdn.net/qq_40989769/article/details/130874660以及这个视频学习&#xff1a; nginx的内存池_哔哩哔哩_bilibilihttps://w…

go逆向符号恢复

前言 之前一直没怎么重视&#xff0c;结果发现每次遇到go的题都是一筹莫展&#xff0c;刷几道题练习一下吧 准备 go语言写的程序一般都被strip去掉符号了&#xff0c;而且ida没有相关的签名文件&#xff0c;没办法完成函数名的识别与字符串的定位&#xff0c;所以第一步通常…

C语言经典小游戏之三子棋(超详解释+源码)

“纵有疾风来&#xff0c;人生不言弃&#xff0c;风乍起&#xff0c;合当奋意向此生。” 今天我们一起来学习一下三子棋小游戏用C语言怎么写出来&#xff1f; 三子棋小游戏 1.游戏规则介绍2.游戏准备3.游戏的实现3.1生成菜单3.2游戏的具体实现3.2.1初始化棋盘3.2.2打印棋盘3.2…

TypeScript【enum 枚举】

导语 在 TypeScript 中&#xff0c;新增了很多具有特性的一些数据类型处理方法&#xff0c;enum 【枚举】就是其中&#xff0c;很具有代表性的一种&#xff0c;所以本章节就来聊聊 在 TypeScript 中如何去运用 enum 【枚举】。 枚举的概念&#xff1a; 枚举&#xff08;Enum&am…

机器学习基础08-模型选择02-分类算法矩阵(基于Pima 数据集)

算法评估矩阵&#xff08;Algorithm Evaluation Metrics&#xff09;用于评估机器学习算法在特定任务上的性能。不同的任务可能会使用不同的评估矩阵&#xff0c;因为每个任务的优劣衡量标准都不同。 分类算法矩阵 分类问题或许是最常见的机器学习问题&#xff0c;并且有多种评…