SpringBoot错误处理机制解析

SpringBoot错误处理----源码解析

文章目录

    • 1、默认机制
    • 2、使用@ExceptionHandler标识一个方法,处理用@Controller标注的该类发生的指定错误
      • 1).局部错误处理部分源码
      • 2).测试
    • 3、 创建一个全局错误处理类集中处理错误,使用==@ControllerAdvice==注解标注
      • 1).全局错误处理部分源码
      • 3).测试
    • 4、SpringMVC错误处理未能处理(上述处理不存在)
        • 1、SpringBoot中自动配置的错误处理机制,基于`ErrorMvcAutoConfiguration`自动配置实现
        • 2、` BasicErrorController`组件
        • 规则如下:
    • 5、自定义错误响应
    • 6、测试
        • 1、在项目的resources/templates/目录下创建一个error文件夹,放入4xx.html、5xx.html
        • 2、在项目的resources/templates/error文件夹中,再放入404.html、500.html
        • 3、浏览器先后测试上述情况

1、默认机制

SpringBoot错误处理的自动配置都在ErrorMvcAutoConfiguration中,两大核心机制:

  • 1.SpringBoot会自适应处理错误,响应页面或JSON数据

  • 2.SpringMVC的错误处理机制依然保留,MVC处理不了,才会交给SpringBoot进行处理。
    在这里插入图片描述(图片来自尚硅谷)

2、使用@ExceptionHandler标识一个方法,处理用@Controller标注的该类发生的指定错误

(默认只能处理这个类的该指定错误)

// @ExceptionHandler源码
@Target({ElementType.METHOD})     // 指定了该注解仅能用于方法
@Retention(RetentionPolicy.RUNTIME)   //指定了注解会在运行时保留,这允许通过反射在运行时获取对注解的访问
@Documented      //注解应该被包含在生成的 JavaDoc 文档中
@Reflective({ExceptionHandlerReflectiveProcessor.class}) 
public @interface ExceptionHandler {Class<? extends Throwable>[] value() default {};       //它定义了一个名为 value 的属性,其类型是一个 Class 数组,这个数组的元素必须是 Throwable 类或其子类。通过使用这个注解时,可以为 value 属性提供一个 Throwable 类型的数组
}

1).局部错误处理部分源码

@Controller         //适配服务端渲染    前后不分离模式开始
public class WelcomeController {//来到首页@GetMapping("/")public String index(){int i=10/0;    //制造错误return "index";}@ResponseBody     //返回的字符串应该直接作为 HTTP 响应体的内容,而不是作为视图名称解析。通常用于返回 JSON 或纯文本等非HTML内容@ExceptionHandler(Exception.class)   //传递到value数组中public String handleException(Exception e){return "Ohho~~~,原因:"+e.getMessage();}}

2).测试

  • 1.启动项目,浏览器访问http://localhost:8080/

  • 2.测试结果(成功处理错误)
    在这里插入图片描述

3、 创建一个全局错误处理类集中处理错误,使用==@ControllerAdvice==注解标注

(这个类是集中处理所有@Controller 发生的错误)

//@ControllerAdvice源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component       //标记类为一个 Spring 组件
public @interface ControllerAdvice {@AliasFor(annotation = Component.class,attribute = "value")String name() default "";@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<?>[] assignableTypes() default {};Class<? extends Annotation>[] annotations() default {};
}

1).全局错误处理部分源码

@ControllerAdvice        //这个类是集中处理所有@Controller发生的错误
public class GlobalExceptionHandler {@ResponseBody@ExceptionHandler(Exception.class)public String handleException(Exception e){return "Ohho~~~统一处理所有错误,原因:"+e.getMessage();}
}

###2).再创建一个类,使用@Controller注解标注

@Controller
public class HelloController {@GetMapping("/haha")public String haha(){int i = 10/0;        //制造错误return "index";}
}

3).测试

  • 1.启动项目,浏览器访问http://localhost:8080/
  • 2.测试结果(成功处理错误)就近原则,执行的是@Controller类中标注了@ExceptionHandler方法的处理
    在这里插入图片描述
  • 3.浏览器访问http://localhost:8080/haha全局错误处理类进行处理
    在这里插入图片描述

4、SpringMVC错误处理未能处理(上述处理不存在)

第一阶段的处理未解决,错误转发到/error,执行后续处理(图中第一阶段失效,第二阶段处理),以下测试过程中,注释掉上文中的全局和局部处理代码

1、SpringBoot中自动配置的错误处理机制,基于ErrorMvcAutoConfiguration自动配置实现

ErrorMvcAutoConfiguration自动装配类中,SpringBoot在底层写好一个 ==BasicErrorController==的组件,专门处理/error这个请求,部分源码如下:

@AutoConfiguration(before = WebMvcAutoConfiguration.class) //指定了该自动配置类在 WebMvcAutoConfiguration 之前进行配置
@ConditionalOnWebApplication(type = Type.SERVLET)    //只有在当前应用是一个 Servlet Web 应用时,这个自动配置才会生效
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })   //只有当类路径中存在 Servlet 和 DispatcherServlet 时,这个自动配置才会生效
@EnableConfigurationProperties({ ServerProperties.class, WebMvcProperties.class }) //启用指定类的配置属性绑定
public class ErrorMvcAutoConfiguration {private final ServerProperties serverProperties; //注入了 ServerProperties 实例。这样的构造方法注入是为了获取应用程序的服务器配置public ErrorMvcAutoConfiguration(ServerProperties serverProperties) {this.serverProperties = serverProperties;  //注入 ServerProperties 实例}//容器中不存在 ErrorAttributes 类型的 Bean 时,才会创建并注册当前方法所返回的 Bean@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();}//在容器中不存在 ErrorController 类型的 Bean 时,才会创建并注册当前方法所返回的 Bean@Bean@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,ObjectProvider<ErrorViewResolver> errorViewResolvers) {return new BasicErrorController(errorAttributes, this.serverProperties.getError(),errorViewResolvers.orderedStream().toList());}...
}
2、 BasicErrorController组件

SpringBoot中默认的server.error.path=/error,即该类就是处理/error请求的,根据不同类型的请求,如果产生 HTML 内容的请求,匹配public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) 这个方法;否则其他请求类型,匹配public ResponseEntity<Map<String, Object>> error(HttpServletRequest request)方法。分别进行处理。(只会匹配其中一个,Spring MVC会尝试匹配与请求路径最匹配的RequestMapping)

  • 1.部分源码:
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {private final ErrorProperties errorProperties;/*** Create a new {@link BasicErrorController} instance.* @param errorAttributes the error attributes* @param errorProperties configuration properties*/public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {this(errorAttributes, errorProperties, Collections.emptyList());}/*** Create a new {@link BasicErrorController} instance.* @param errorAttributes the error attributes* @param errorProperties configuration properties* @param errorViewResolvers error view resolvers*/public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties,List<ErrorViewResolver> errorViewResolvers) {super(errorAttributes, errorViewResolvers);Assert.notNull(errorProperties, "ErrorProperties must not be null");this.errorProperties = errorProperties;}@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)   //请求类型为HTML 文本public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));response.setStatus(status.value());ModelAndView modelAndView = resolveErrorView(request, response, status, model);return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);}@RequestMappingpublic ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {HttpStatus status = getStatus(request);if (status == HttpStatus.NO_CONTENT) {return new ResponseEntity<>(status);}Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));return new ResponseEntity<>(body, status);}...
}
  • 2.匹配成功之后,错误页面解析的核心代码

    //1、解析错误的自定义视图地址
    ModelAndView modelAndView = resolveErrorView(request, response, status, model);
    //2、如果解析不到错误页面的地址,默认的错误页就是 error
    return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
    
  • 3.在ErrorMvcAutoConfiguration自动装配类中,SpringBoot在底层写好一个 ==DefaultErrorViewResolver==的组件,注入到了容器中

    	@Configuration(proxyBeanMethods = false)@EnableConfigurationProperties({ WebProperties.class, WebMvcProperties.class })static class DefaultErrorViewResolverConfiguration {private final ApplicationContext applicationContext;private final Resources resources;DefaultErrorViewResolverConfiguration(ApplicationContext applicationContext, WebProperties webProperties) {this.applicationContext = applicationContext;this.resources = webProperties.getResources();}@Bean@ConditionalOnBean(DispatcherServlet.class)@ConditionalOnMissingBean(ErrorViewResolver.class)DefaultErrorViewResolver conventionErrorViewResolver() {return new DefaultErrorViewResolver(this.applicationContext, this.resources);}}
    
  • 4.在DefaultErrorViewResolver中定义了错误页的默认规则,功能如下:

    • 如果在类路径下,查看是否存在 error/错误码 的页面,存在就返回该视图;
    • 否则,去4个CLASSPATH_RESOURCE_LOCATIONS路径下,查看是否写了 error/错误码.html 的页面,存在则返回该视图;
    • 都不存在,则modelAndView=null;则判断是否有 error/4xx 或者 error/5xx 的页面,存在则返回该视图
    • 否则,去4个CLASSPATH_RESOURCE_LOCATIONS路径下,查看是否写了 error/4xx.html 或者 error/5xx.html 的页面,存在则返回该视图;
    public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {...private static final Map<Series, String> SERIES_VIEWS;static {Map<Series, String> views = new EnumMap<>(Series.class);views.put(Series.CLIENT_ERROR, "4xx");views.put(Series.SERVER_ERROR, "5xx");SERIES_VIEWS = Collections.unmodifiableMap(views);}// 查看是否存在 error/错误码 的页面,存在就返回该视图// 不存在,则判断是否有  error/4xx  或者  error/5xx  的页面,存在则返回该视图@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);}return modelAndView;}// 在类路径下,查看是否存在 error/错误码 的模板引擎,存在就返回该视图;// 否则去下面的4个CLASSPATH_RESOURCE_LOCATIONS路径下,查看是否写了  error/错误码.html 的页面,存在则返回该视图private ModelAndView resolve(String viewName, Map<String, Object> model) {String errorViewName = "error/" + viewName;TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,this.applicationContext);if (provider != null) {return new ModelAndView(errorViewName, model);}return resolveResource(errorViewName, model);}//去下面的4个CLASSPATH_RESOURCE_LOCATIONS路径下,查看是否写了  error/错误码.html  的页面,存在则返回该视图//this.resources.getStaticLocations()//private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",//			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };private ModelAndView resolveResource(String viewName, Map<String, Object> model) {for (String location : this.resources.getStaticLocations()) {try {Resource resource = this.applicationContext.getResource(location);resource = resource.createRelative(viewName + ".html");if (resource.exists()) {return new ModelAndView(new HtmlResourceView(resource), model);}}catch (Exception ex) {}}return null;}...
    }
    
  • 5.在ErrorMvcAutoConfiguration自动装配类中,向容器中放入了一个默认名为error的视图,提供了默认的白页功能,如果上述都无法处理

    	@Configuration(proxyBeanMethods = false)@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)@Conditional(ErrorTemplateMissingCondition.class)protected static class WhitelabelErrorViewConfiguration {private final StaticView defaultErrorView = new StaticView();//   注入了error视图@Bean(name = "error")@ConditionalOnMissingBean(name = "error")public View defaultErrorView() {return this.defaultErrorView;}// If the user adds @EnableWebMvc then the bean name view resolver from// WebMvcAutoConfiguration disappears, so add it back in to avoid disappointment.@Bean@ConditionalOnMissingBeanpublic BeanNameViewResolver beanNameViewResolver() {BeanNameViewResolver resolver = new BeanNameViewResolver();resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);return resolver;}}
    

    默认的白页源码,就在类ErrorMvcAutoConfiguration中定义的

    private static class StaticView implements View {private static final MediaType TEXT_HTML_UTF8 = new MediaType("text", "html", StandardCharsets.UTF_8);private static final Log logger = LogFactory.getLog(StaticView.class);@Overridepublic void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)throws Exception {if (response.isCommitted()) {String message = getMessage(model);logger.error(message);return;}response.setContentType(TEXT_HTML_UTF8.toString());StringBuilder builder = new StringBuilder();Object timestamp = model.get("timestamp");Object message = model.get("message");Object trace = model.get("trace");if (response.getContentType() == null) {response.setContentType(getContentType());}builder.append("<html><body><h1>Whitelabel Error Page</h1>").append("<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>").append("<div id='created'>").append(timestamp).append("</div>").append("<div>There was an unexpected error (type=").append(htmlEscape(model.get("error"))).append(", status=").append(htmlEscape(model.get("status"))).append(").</div>");if (message != null) {builder.append("<div>").append(htmlEscape(message)).append("</div>");}if (trace != null) {builder.append("<div style='white-space:pre-wrap;'>").append(htmlEscape(trace)).append("</div>");}builder.append("</body></html>");response.getWriter().append(builder.toString());}private String htmlEscape(Object input) {return (input != null) ? HtmlUtils.htmlEscape(input.toString()) : null;}private String getMessage(Map<String, ?> model) {Object path = model.get("path");String message = "Cannot render error page for request [" + path + "]";if (model.get("message") != null) {message += " and exception [" + model.get("message") + "]";}message += " as the response has already been committed.";message += " As a result, the response may have the wrong status code.";return message;}@Overridepublic String getContentType() {return "text/html";}}
    
  • 6.在ErrorMvcAutoConfiguration自动装配类中,封装了JSON格式的错误信息(初始化了错误的类型、错误的状态码、路径、栈信息、时间戳等信息)

    @Bean
    @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
    public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();
    }
    
规则如下:
  • 1.解析一个错误页:

    • 如果发生了500、404、503、403 这些错误
        1. 如果有模板引擎,默认在 classpath:/templates/error/精确码.html
        1. 如果没有模板引擎,在静态资源文件夹下找 精确码.html
    • 如果匹配不到精确码.html这些精确的错误页,就去找5xx.html4xx.html模糊匹配
        1. 如果有模板引擎,默认在 classpath:/templates/error/5xx.html
        1. 如果没有模板引擎,在静态资源文件夹下找 5xx.html
  • 2.如果模板引擎路径templates下有 error.html页面,就直接渲染

5、自定义错误响应

​ 1) 自定义json响应:使用文章第2和第3部分介绍的,使用注解进行统一的异常处理

​ 2)自定义页面响应:根据第4部分介绍的规则,在对应的项目路径"classpath:/METAINF/resources/","classpath:/resources/","classpath:/static/", "classpath:/public/"或者模板引擎目录下,定义错误页面即可。

6、测试

1、在项目的resources/templates/目录下创建一个error文件夹,放入4xx.html、5xx.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>4xx.html
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
5xx.html
</body>
</html>
2、在项目的resources/templates/error文件夹中,再放入404.html、500.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
404.html
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
500.html
</body>
</html>
3、浏览器先后测试上述情况
  • 1.访问一个不存在的路径;
  • 2.制造除0错误。

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

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

相关文章

基于java技术的电子商务支撑平台

摘 要 随着网络技术的发展&#xff0c;Internet变成了一种处理日常事务的交互式的环境。互联网上开展各种服务已经成为许多企业和部门的急切需求。Web的普遍使用从根本上改变了人们的生活方式、工作方式&#xff0c;也改变了企业的经营方式和服务方式。人们可以足不出户办理各…

财务管理在IT服务管理中的重要作用

官方网站 www.itilzj.com 文档资料: wenku.itilzj.com 财务管理作为一种管理组织财务资源的方法&#xff0c;在IT服务领域扮演着关键的角色。其涵盖的范围涉及预算编制、成本控制、投资决策、财务报告和绩效评估等多个方面&#xff0c;直接关系到IT服务的财务健康和整体运作。…

Csharp(C#)无标题栏窗体拖动代码

C#&#xff08;C Sharp&#xff09;是一种现代、通用的编程语言&#xff0c;由微软公司在2000年推出。C#是一种对象导向的编程语言&#xff0c;它兼具C语言的高效性和Visual Basic语言的易学性。C#主要应用于Windows桌面应用程序、Windows服务、Web应用程序、游戏开发等领域。C…

蓝桥杯每日一题2023.12.3

题目描述 1.移动距离 - 蓝桥云课 (lanqiao.cn) 题目分析 对于此题需要对行列的关系进行一定的探究&#xff0c;所求实际上为曼哈顿距离&#xff0c;只需要两个行列的绝对值想加即可&#xff0c;预处理使下标从0开始可以更加明确之间的关系&#xff0c;奇数行时这一行的数字需…

做外贸如何写开发信?外贸邮件营销怎么写?

外贸业务员写开发信的技巧&#xff1f;撰写客户开发信模板详解&#xff01; 外贸经营是一项竞争激烈的行业&#xff0c;写好开发信是吸引客户、建立合作关系的重要一环。蜂邮EDM将为您详细介绍如何撰写出色的开发信&#xff0c;以吸引客户的眼球&#xff0c;引领他们与您建立联…

【数电笔记】17-具体函数的卡诺图填入

目录 说明&#xff1a; 用卡诺图表示逻辑函数 1. 基本步骤 2. 例题 2.1 例1-真值表转换卡诺图 2.2 例2-标准与或式画卡诺图 2.3 例3-非标准与或式画卡诺图&#xff08;常见,重点掌握&#xff09; 说明&#xff1a; 笔记配套视频来源&#xff1a;B站&#xff1b;本系列笔…

el-pagination 纯前端分页

需求&#xff1a;后端把所有数据都返给前端&#xff0c;前端进行分页渲染。 实现思路&#xff1a;先把数据存储到一个大数组中&#xff0c;然后调用方法进行切割。主要使用数组的slice方法 所有代码&#xff1a; html <template><div style"padding: 20px&qu…

分享74个节日PPT,总有一款适合您

分享74个节日PPT&#xff0c;总有一款适合您 74个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/18YHKkyJsplx-Gjj7ofpFrg?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

短波红外相机的原理及应用场景

短波红外 (简称SWIR&#xff0c;通常指0.9~1.7μm波长的光线) 是一种比可见光波长更长的光。这些光不能通过“肉眼”看到&#xff0c;也不能用“普通相机”检测到。由于被检测物体的材料特性&#xff0c;一些在可见光下无法看到的特性&#xff0c;却能在近红外光下呈现出来&…

深度学习数据集的划分(加载kaggle的dog数据,多gpu训练加载参数)待更新

待更新 把dog-breed-identification.zip 文件放到data文件目录下&#xff1a; 该文件解压之后得到如下&#xff1a; 遍历train中的所有文件&#xff0c;train_file.split(‘.’)[0]是根据.划分这个文件名&#xff0c;得到前缀和后缀&#xff0c;下标为0的是去掉后缀的文件名…

国家图书馆论文检索证明申请步骤

国家图书馆论文检索证明申请步骤 登录国家图书馆 咨询提交平台 点击论文收引查证 添加附件这一块&#xff0c;需要自己制作一个有格式的EXCEL 卷&#xff0c;期&#xff0c;页码如何查询&#xff1f; 输入自己的联系方式等待工作人员联系即可

接口获取数据控制台打印有值但是展开又没有了

谷歌浏览器只会展现响应式数据最后的结果&#xff0c;证明原来接口是有值的&#xff0c;后面对这个数据进行操作后&#xff0c;最终没有值了。所以对数据进行操作时最好对数据进行一次深拷贝 JSON.parse(JSON.stringify(data))

堆排序(C语言)

前言 在上一篇内容&#xff1a;大小堆的实现&#xff08;C语言&#xff09;&#xff0c;我们实现了关于创建大小堆的各函数与实现。但是如果突然要使用一个堆排序但是此时并没有一个现成的堆&#xff0c;这就需要花费时间去新建实现堆的插入删除这些操作从而实现一个堆&#xf…

通达信指标公式18:教你2行代码,选股出含有龙字辈的股票

“问财”是同花顺平台上一款专业的财经AI助手&#xff0c;融合了自然语言和语音问答机器人。它提供了多维度的股票、基金、债券数据&#xff0c;并支持自然语言搜索&#xff0c;能够轻松查找所需的信息。对于个人投资者来说&#xff0c;问财最好用的功能是它的条件选股和短线复…

【C++11/线程相关】thread类编写多线程、mutex互斥锁和lock_guard、atomic原子类型

目录 通过thread类编写C多线程程序线程间互斥——mutex互斥锁和lock_guardmutex互斥锁lock_guard 线程间通信C11实现生产者与消费者模型 基于CAS操作的atomic原子类型 橙色 通过thread类编写C多线程程序 为什么结果没有子线程中所打印的字符串呢&#xff1f;因为通过detach进…

代码随想录算法训练营 ---第五十三天

第一题&#xff1a; 简介&#xff1a; 本题和昨天的最大重复子串问题很相似&#xff0c;只不过本题不一定是连续的。 动规五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;长度为i-1 的字符串text1与长度为j-1的…

Vue实现图片预览(Viewer.js)

摘要&#xff1a; vue项目开发中遇到一个图片预览的需求&#xff0c;可以切换下一张&#xff0c;就是花里胡哨的&#xff0c;所以找viewer.js的插件 npm install v-viewer -S在项目main.js中加入&#xff1a; Viewer.setDefaults用于更改默认配置&#xff0c;比如我不想要显示…

嘴尚绝卤味:健康卤味,未来餐饮市场的新星

随着人们生活水平的提高&#xff0c;对于吃的要求也越来越高。尤其是在快节奏的现代社会中&#xff0c;健康饮食成为了越来越多人的追求。在这种背景下&#xff0c;健康卤味这一新兴食品品类应运而生&#xff0c;成为了餐饮市场的新宠儿。 一、健康卤味的崛起 传统的卤味制作过…

内容过滤算法:构建数字世界的守护者

目录 引言 1. 内容过滤算法概述 2. 内容过滤算法的分类 2.1 关键词过滤算法 2.2 统计模型 2.3 机器学习算法 2.4 深度学习算法 3. 内容过滤算法在实际应用中的体现 3.1 电子邮件过滤 3.2 社交媒体内容过滤 3.3 网络搜索引擎 4. 内容过滤算法的挑战与未来发展 4.1 对…

编程题:电话号码

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 &#x1f4d1;题目解析 这个题目比较…