【SpringMVC】JSON注解异常处理的使用

news2025/1/23 7:21:14

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟在这里,我要推荐给大家我的专栏《Spring MVC》。🎯🎯

🚀无论你是编程小白,还是有一定基础的程序员,这个专栏都能满足你的需求。我会用最简单易懂的语言,带你走进Spring MVC的世界,让你从零开始,一步步成为JAVA大师。🚀🏆

🌈让我们一起在SpringMVC的世界里畅游吧!🌈🌈

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请记得给我点赞哦!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

 请添加图片描述 

目录

 一、JSON数据返回

1.1.前言

1.2.Jackson的介绍

1.2.1.什么是Jackson

1.2.2.常用注解

1.3.使用注解

1.3.1.导入依赖

1.3.2.配置spring-mvc.xml

1.3.3.案例实战

二、异常处理

2.1.为什么要全局异常处理

2.2.异常处理思路

2.3.SpringMVC异常分类

2.4.案例实战

2.4.1.异常处理方式①

2.4.2.异常处理方式②

2.4.3.异常处理方式③

2.5.响应封装类


 一、JSON数据返回

1.1.前言

JSON是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。JSON的常用场景包括:

  • 前后端分离的项目中,后端向前端传送数据时 。
  •  Ajax异步访问数据。
  • RPC远程调用。

除了JSON,还有其他的数据传输格式,如XML等。但是由于XML格式的特点,它在Web开发中使用较少。

1.2.Jackson的介绍

1.2.1.什么是Jackson

Jackson是一个Java库,用于将Java对象转换为JSON格式,以及将JSON格式转换为Java对象。它提供了一种简单的方式来序列化和反序列化Java对象,使得它们可以很容易地在Java应用程序和Web服务之间进行传输。

Jackson库是一个开源项目,由FasterXML开发。它是目前最流行的Java JSON库之一,被广泛应用于各种Java项目中。

优点:

  • 容易使用,提供了高层次外观,简化常用的用例。

  • 无需创建映射,API提供了默认的映射大部分对象序列化。

  • 性能高,快速,低内存占用

  • 创建干净的json

  • 不依赖其他库

  • 代码开源

1.2.2.常用注解

注解名说明
@JsonIgnore用于忽略某个属性或方法,不参与序列化或反序列化。
@JsonProperty用来指定序列化和反序列化的属性名映射。
@JsonSerialize用来指定序列化时使用的类。
@JsonDeserialize用来指定反序列化时使用的类。
@JsonInclude用来指定包含的属性名。
@JsonIncludeAll包含所有属性,除了上面提到的属性。
@JsonAnyGetter用于处理Map中的值。
@JsonAnySetter用于处理Map中的值。
@JsonUnwrapped将JSON字符串中的包装类型(如List、Map等)转换为对应的Java对象。
@JsonFormat用于格式化日期、时间和数字等类型的序列化/反序列化。
@JsonIgnoreProperties作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉

下面是一个简单的示例:

假设有一个Person类:

public class Person {
    private String name;
    private int age;
    @JsonIgnoreProperties({"address"}) // 忽略address属性的序列化和反序列化
    private Address address;
    // getter and setter methods...
}

在序列化时,只有name和age属性会被序列化到JSON中:

ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(person);

在反序列化时,只有name和age属性会被反序列化为Java对象:

Person person = objectMapper.readValue(json, Person.class);

1.3.使用注解

1.3.1.导入依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.3</version>
</dependency> 

1.3.2.配置spring-mvc.xml

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
        	<ref bean="mappingJackson2HttpMessageConverter"/>
        </list>
    </property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件-->
    <property name="supportedMediaTypes">
        <list>
            <value>text/html;charset=UTF-8</value>
            <value>text/json;charset=UTF-8</value>
            <value>application/json;charset=UTF-8</value>
        </list>
    </property>
</bean>

1.3.3.案例实战

@ResponseBody使用

@ResponseBody注解的作用是将Controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。

小贴士:

在使用此注解之后不会再走视图解析器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

以下我会以JSON格式的不同情况来演示数据回显。

JsonController.java

@Controller
@RequestMapping("/stu/json")
public class JsonController {

    @Autowired
    private StudentBiz stubiz;

    /**
     * 返回List<T>
     * @param req
     * @param Student
     * @return
     */
    @ResponseBody
    @RequestMapping("/list")
    public List<Student> list(HttpServletRequest req, Student Student){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<Student> lst = this.stubiz.selectBySnamePager(Student, pageBean);
        return lst;
    }

    /**
     * 返回T
     * @param req
     * @param Student
     * @return
     */
    @ResponseBody
    @RequestMapping("/load")
    public Student load(HttpServletRequest req, Student Student){
        if(Student.getSid() != null){
            List<Student> lst = this.stubiz.selectBySnamePager(Student, null);
            return lst.get(0);
        }
        return null;
    }


    /**
     * 返回List<Map>
     * @param req
     * @param Student
     * @return
     */
    @ResponseBody
    @RequestMapping("/mapList")
    public List<Map> mapList(HttpServletRequest req, Student Student){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<Map> lst = this.stubiz.mapListPager(Student, pageBean);
        return lst;
    }

    /**
     * 返回Map
     * @param req
     * @param Student
     * @return
     */
    @ResponseBody
    @RequestMapping("/mapLoad")
    public Map mapLoad(HttpServletRequest req, Student Student){
        if(Student.getSid() != null){
            List<Map> lst = this.stubiz.mapListPager(Student, null);
            return lst.get(0);
        }
        return null;
    }


    @ResponseBody
    @RequestMapping("/all")
    public Map all(HttpServletRequest req, Student Student){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<Student> lst = this.stubiz.selectBySnamePager(Student, pageBean);
        Map map = new HashMap();
        map.put("lst",lst);
        map.put("pageBean",pageBean);
        return map;
    }

    @ResponseBody
    @RequestMapping("/jsonStr")
    public String jsonStr(HttpServletRequest req, Student Student){
        return "clzEdit";
    }

}

返回List<T>:

返回T:

返回List<Map>:

返回Map:

返回JSON数组:

返回字符串:

总结:

通过以上的案例我们可以看到返回T和List<T>都可以通过Map来做到,所以我们在做需求的时候应当灵活应用,如果返回的是字符串虽然我们有这个jsp页面,但也不会走视图解析器,这一点我们前面也说了这里也验证了。给大家提一个小技巧,如果你的Controller类里面,都是返回的JSON数据可以将@ResponseBody注解在类上,如果我们的类上同时出现以下两个注解:@Controller和@ResponseBody就可以使用@RestController。

小贴士:

@Controller注解用于标识一个类是Spring MVC中的控制器,即处理用户请求并返回响应的组件。

@ResponseBody注解用于将方法返回的对象转换为JSON格式的字符串,并将其作为HTTP响应体发送给客户端。

因此,@RestController注解合集的含义是:将一个类标记为Spring MVC控制器,并使用@ResponseBody注解将方法返回的对象转换为JSON格式的字符串,以便于在浏览器或其他客户端中进行访问。

二、异常处理

2.1.为什么要全局异常处理

在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护 ,全局异常处理是指在应用程序中对所有异常进行捕获和处理,而不是仅仅对特定的异常进行处理。

以下是一些原因说明为什么要全局异常处理:

  1. 统一处理异常:全局异常处理可以确保在应用程序的所有部分都使用相同的异常处理逻辑,从而使代码更加一致和易于维护。

  2. 简化代码:通过将异常处理逻辑集中在一个地方,可以减少代码冗余,并使代码更易于阅读和维护。

  3. 提高安全性:全局异常处理可以帮助防止未处理的异常导致的潜在安全问题,例如泄露敏感信息或允许攻击者执行恶意代码。

  4. 更好的用户体验:通过全局异常处理,应用程序可以在出现异常时给出更有用和友好的错误消息,从而提高用户体验。

综上所述,全局异常处理可以使应用程序更加健壮、一致、易于维护和安全,同时提供更好的用户体验。

小贴士:运行时异常和编译时异常的区别?

  1. 编译时异常(Checked Exception): 编译时异常是在编译阶段被检查出来的异常,必须进行处理,否则编译器会报错。常见的编译时异常有IOException、SQLException等。处理方式可以使用try-catch语句块来捕获和处理这些异常。

  2. 运行时异常(Runtime Exception): 运行时异常是在程序运行期间抛出的异常,如果不进行处理,程序会崩溃。常见的运行时异常有NullPointerException、ArrayIndexOutOfBoundsException等。这些异常通常是由程序逻辑错误引起的,因此无法在编译时进行检测。

2.2.异常处理思路

系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

具体来说,异常处理的思路包括以下几个方面:

  1. 确定异常类型:在进行异常处理之前,需要先确定可能会出现哪些异常情况,以及这些异常情况对应的异常类型。

  2. 添加异常处理代码:在程序中添加相应的异常处理代码,用于捕获可能出现的异常,并进行相应的处理。

  3. 处理异常:根据不同的异常类型,采取不同的处理方式。例如,对于运行时异常,可以采取打印错误信息等方式进行处理;对于受检异常,则需要在方法声明中添加throws关键字,并在调用该方法时进行try-catch处理。

  4. 优化异常处理:在实际应用中,需要根据具体情况对异常处理进行优化。例如,可以使用多线程机制来提高程序的性能;或者使用日志系统来记录程序运行过程中出现的异常情况等。

2.3.SpringMVC异常分类

SpringMVC中的异常处理方式有三种:

  • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;

  • 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;

  • 使用@ControllerAdvice + @ExceptionHandler

 

2.4.案例实战

2.4.1.异常处理方式①

SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。

spring-mvc.xml

<!-- springmvc提供的简单异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!-- 定义默认的异常处理页面 -->
    <property name="defaultErrorView" value="error"/>
    <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --> 
    <property name="exceptionAttribute" value="ex"/>
    <!-- 定义需要特殊处理的异常,这是重要点 --> 
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.RuntimeException">error</prop>
        </props>
    	<!-- 还可以定义其他的自定义异常 -->
    </property>
</bean> 

error.jsp 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>系统繁忙</title>
</head>
<body>
${ex}<br>
<img src="${pageContext.request.contextPath }/static/1.jpg" style="height: 1000px;width: 1550px;">

</body>
</html>

注:页面跳转由SpringMVC来接管了,所以此处的定义默认的异常处理页面都应该配置成逻辑视图名。

我们没有配置这段代码之前,以下的页面是我们不想看到的,看看配置后是怎么样的吧?

配置异常处理:

明显后面做了异常处理的看起来更为舒服。

2.4.2.异常处理方式②

创建一个名为exception的包将我们的GlobalException类放入其中。

GlobalException.java

public class GlobalException extends RuntimeException {
    public GlobalException() {
    }

    public GlobalException(String message) {
        super(message);
    }

    public GlobalException(String message, Throwable cause) {
        super(message, cause);
    }

    public GlobalException(Throwable cause) {
        super(cause);
    }

    public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

创建一个名为Component的包将我们的GlobalExceptionHandler类放入其中。

GlobalExceptionHandler.java

@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {

    //    跳转错误页面
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            mv.addObject("ex",globalException.getMessage());
            mv.addObject("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            mv.addObject("ex",runtimeException.getMessage());
            mv.addObject("msg","运行时异常....");
        }else{
            mv.addObject("ex",e.getMessage());
            mv.addObject("msg","其他异常....");
        }
        return mv;
    }
}

1.通过instanceof判断异常类型

2.通过设置mv.setView(new MappingJackson2JsonView())方式返回JSON数据

这时候我们来访问以下http://localhost:8080/xwzyssm/stu/json/jsonStr

因为异常处理会根据我们的异常问题进行判断map保存输出到前端,所以在JSP页面上用EL表达式捕捉msg信息就可以知道问题是什么更为直观。

2.4.3.异常处理方式③

GlobalExceptionResolver.java

@ControllerAdvice
public class GlobalExceptionResolver {


// 返回错误json数据
    @ResponseBody
    @ExceptionHandler
    public Map handler(Exception e){
        Map map = new HashMap();
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            map.put("ex",globalException.getMessage());
            map.put("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            map.put("ex",runtimeException.getMessage());
            map.put("msg","运行时异常....");
        }else {
            map.put("ex",e.getMessage());
            map.put("msg","其它异常....");
        }
        return map;
    }
}

 这种方式是将我们的错误信息进行map保存然后转换为JSON格式输出在页面上。

 这时候我们来访问以下 http://localhost:8080/xwzyssm/stu/json/jsonStr

2.5.响应封装类

通过我刚刚的解释想必大家对异常处理有了一定的理解,但是大家有没有发现,异常处理类中反复的需要定义Map,随后.put添加数据,我们能否对以上代码进行优化呢?能!!下面请欣赏小编所需的R工具类。

R.java

public class R extends HashMap {
    public R data(String key, Object value) {
        this.put(key, value);
        return this;
    }

    public static R ok(int code, String msg) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg);
        return r;
    }

    public static R error(int code, String msg) {
        R r = new R();
        r.data("success", false).data("code", code).data("msg", msg);
        return r;
    }

    public static R ok(int code, String msg,Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("data", data);
        return r;
    }

    public static R ok(int code, String msg, long count, Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("count", count).data("data", data);
        return r;
    }
}

GlobalExceptionResolver.java

@ControllerAdvice
public class GlobalExceptionResolver {

    // 响应封装类
    @ResponseBody
    @ExceptionHandler
    public Map handler(Exception e){

        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            return R.ok(500,"全局异常....",globalException.getMessage());
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            return R.ok(500,"运行时异常....",runtimeException.getMessage());
        }else {
            return R.ok(500,"其他异常....",e.getMessage());
        }
    }
}

  这时候我们来访问以下 http://localhost:8080/xwzyssm/stu/json/jsonStr

 请添加图片描述 

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

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

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

相关文章

【Axure高保真原型】日历日期原型模板

今天和大家分享日历日期的原型模板&#xff0c;包括月计划、周计划、日计划的原型案例&#xff0c;以及日期、时间、月份、区间选择器……具体效果可以点击下方视频观看 【原型预览及下载地址】 Axure 原型 备用地址&#xff1a;Untitled Document 【原型效果】 【原型效果…

ABAP 获取信贷超额函数

业务需求&#xff1a;在创建销售订单时&#xff0c;信贷超额不会影响单据正常生成&#xff0c;前台信贷超额消息时前台弹框式警告&#xff0c;故而不会在BAPI RETURN中返回&#xff0c;也许需要获取这类消息&#xff0c;返回给外围系统。 函数&#xff1a;SD_DELIVERY_CREDIT_C…

利用面向对象方法,处理数据文件【Python】

题目背景&#xff1a;处理两份数据文件&#xff08;文本数据和JSON数据&#xff09;&#xff0c;用面向对象的方法&#xff0c;效果图用柱状图呈现。 本题思路&#xff1a; 1.首先&#xff0c;创建一个【基础数据类】&#xff0c;名为Record&#xff0c;它将包含成员属性和成员…

【数据结构-堆】堆

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

嵌入式行业这个领域是否值得坚持

今日话题&#xff0c;嵌入式行业&#xff0c;特别是对于嵌入式新人&#xff0c;是否值得坚持这个领域&#xff1f;对于想要进入嵌入式行业的人来说&#xff0c;坚持是明智的选择。这个领域涉及硬件和软件&#xff0c;技术更新较慢&#xff0c;但它也为你提供了积累经验的机会。…

mysql学习查缺补漏1---基础部分(小滴课堂)

举例&#xff1a; DDL&#xff1a;建库&#xff0c;建表。 DML&#xff1a;对表的数据进行增删改操作。 DQL&#xff1a;对数据进行查询。 DCL&#xff1a;对用户的权限进行设置。 create table teacher as select * from student where 12; 该条语句只用于复制表结构&…

Kubernetes 使用configmap挂载卷给Pod内的nginx容器

目录 实验&#xff1a;使用configmap挂载卷给Pod内的nginx容器 1、创建nginx.conf配置文件&#xff08;必须由nginx镜像里的nginx.conf修改而来&#xff0c;防止出现配置不相似的情况出现&#xff0c;导致访问不了nginx网页&#xff09; 2、通过nginx.conf文件创建configmap容…

Java 代理模式之静态代理与动态代理

1&#xff0c;代理模式 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。 代理模式的目的&#xff1a; &#xff08;1&#xff09;通过引入代理对象的方式来间接访问目标对象&#xff0c;防…

对话式人工智能(Conversational AI):提高模型的智能程度和扩展能力

对话式人工智能的趋势与挑战 对话式人工智能 (AI) 已经出现在许多家庭的客厅、汽车和在线购物体验中。聊天机器人、语音助手、智能扬声器、交互式语音识别系统&#xff1a;所有这些都是对话式 AI 的示例。由于该领域通过增强的客户体验提供了更多可访问性&#xff0c;因此吸引…

PHP自己的框架2.0结合容器技术(重构篇二)

目录 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 3、框架使用容器类来执行public/index.php 4、运行效果还是一样 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 什么是容器&#xff1f;容器就相当于盒子&#xff0c;把很多类放里…

录音怎么转换成mp3格式?支持二十多种格式

录音怎么转换成mp3格式&#xff1f;在我们的日常生活和工作中&#xff0c;录音是一项非常有用的工具&#xff0c;随着手机以及录音设备越来越普及化&#xff0c;让录音这件事情变得非常的简单&#xff0c;录音可以帮助我们解决非常多的事情。例如通过录音&#xff0c;我们可以记…

Linux C++ OpenVINO 物体检测 Demo

目录 main.cpp #include <iostream> #include <string> #include <vector> #include <openvino/openvino.hpp> #include <opencv2/opencv.hpp> #include <dirent.h> #include <stdio.h> #include <time.h> #include …

OJ练习第171题——复制带随机指针的链表

复制带随机指针的链表 力扣链接&#xff1a;138. 复制带随机指针的链表 题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个…

Temu新手入门需要注意哪些细节?如何在Temu中添加尺码?

要在temu平台取得商业成功&#xff0c;创业者们必须注重商品策划和市场调研、关注市场动向和用户反馈、建立良好的互动和交流机制、发挥temu的优势和特点&#xff0c;本文介绍了temu新手入门需要注意细节以及如何在TEMU中添加尺码&#xff0c;快来学习一下吧。 temu新手入门需…

使用Javassist修改组件化 Router

工程目录图 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 代码&#xff1a;TransformDemo

Python中数据去重的重要性、技巧和实现代码

在数据处理和分析的过程中&#xff0c;数据去重是数据处理和分析的关键步骤之一。重复的数据会导致分析结果的偏差&#xff0c;影响决策的准确性。通过数据去重&#xff0c;我们可以确保分析所使用的数据集是干净、准确的&#xff0c;从而提高分析结果的可靠性&#xff0c;Pyth…

【LeetCode题目详解】第十章 单调栈part03 84.柱状图中最大的矩形(day60补)

本文章代码以c为例&#xff01; 一、力扣第84题&#xff1a;柱状图中最大的矩形 题目&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 …

【数据结构】—堆详解(手把手带你用C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;水星—今泉愛夏 1:10 ━━━━━━️&#x1f49f;──────── 4:23 …

掌控你的Mac——用Bookshelf Library简化文件管理

Bookshelf Library for Mac是一款高效的文件索引管理工具&#xff0c;它可以帮助你轻松整理和查找Mac上的所有文档和书籍。下面我们来看看这款工具的五个特点。 安装&#xff1a;Bookshelf Library for Mac(文件索引管理工具)v6.3.4激活版 第一&#xff0c;Bookshelf Library…

【广州华锐互动】工业零件拆装VR培训:无需前往现场,提高学习效率

工业零件拆装VR培训是一种新兴的培训方式&#xff0c;通过虚拟现实技术将设备拆解过程进行模拟&#xff0c;让学员在虚拟环境中进行实际操作和学习。这种培训方式具有许多益处&#xff0c;本文将对其进行详细阐述。 首先&#xff0c;工业零件拆装VR培训可以提高学员的学习效率。…