SpringBoot接口 - 如何统一异常处理
SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?
为什么要优雅的处理异常
如果我们不统一的处理异常,经常会在controller层有大量的异常处理的代码, 比如:
@Slf4j
@Api(value = "User Interfaces", tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {/*** http://localhost:8080/user/add .** @param userParam user param* @return user*/@ApiOperation("Add User")@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)@PostMapping("add")public ResponseEntity<String> add(@Valid @RequestBody UserParam userParam) {// 每个接口充斥着大量的异常处理try {// do something} catch(Exception e) {return ResponseEntity.fail("error");}return ResponseEntity.ok("success");}
}
那怎么实现统一的异常处理,特别是结合参数校验等封装?
实现案例
简单展示通过@ControllerAdvice进行统一异常处理。
@ControllerAdvice异常统一处理
对于400参数错误异常
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** exception handler for bad request.** @param e* exception* @return ResponseResult*/@ResponseBody@ResponseStatus(code = HttpStatus.BAD_REQUEST)@ExceptionHandler(value = { BindException.class, ValidationException.class, MethodArgumentNotValidException.class })public ResponseResult<ExceptionData> handleParameterVerificationException(@NonNull Exception e) {ExceptionData.ExceptionDataBuilder exceptionDataBuilder = ExceptionData.builder();log.warn("Exception: {}", e.getMessage());if (e instanceof BindException) {BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).forEach(exceptionDataBuilder::error);} else if (e instanceof ConstraintViolationException) {if (e.getMessage() != null) {exceptionDataBuilder.error(e.getMessage());}} else {exceptionDataBuilder.error("invalid parameter");}return ResponseResultEntity.fail(exceptionDataBuilder.build(), "invalid parameter");}}
对于自定义异常
/*** handle business exception.** @param businessException* business exception* @return ResponseResult*/
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ResponseResult<BusinessException> processBusinessException(BusinessException businessException) {log.error(businessException.getLocalizedMessage(), businessException);// 这里可以屏蔽掉后台的异常栈信息,直接返回"business error"return ResponseResultEntity.fail(businessException, businessException.getLocalizedMessage());
}
对于其它异常
/*** handle other exception.** @param exception* exception* @return ResponseResult*/
@ResponseBody
@ExceptionHandler(Exception.class)
public ResponseResult<Exception> processException(Exception exception) {log.error(exception.getLocalizedMessage(), exception);// 这里可以屏蔽掉后台的异常栈信息,直接返回"server error"return ResponseResultEntity.fail(exception, exception.getLocalizedMessage());
}
Controller接口
(接口中无需处理异常)
@Slf4j
@Api(value = "User Interfaces", tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {/*** http://localhost:8080/user/add .** @param userParam user param* @return user*/@ApiOperation("Add User")@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)@PostMapping("add")public ResponseEntity<UserParam> add(@Valid @RequestBody UserParam userParam) {return ResponseEntity.ok(userParam);}
}
运行测试
这里用postman测试下
进一步理解
我们再通过一些问题来帮助你更深入理解@ControllerAdvice。
@ControllerAdvice还可以怎么用?
除了通过@ExceptionHandler注解用于全局异常的处理之外,@ControllerAdvice还有两个用法:
@InitBinder注解
用于请求中注册自定义参数的解析,从而达到自定义请求参数格式的目的;
比如,在@ControllerAdvice注解的类中添加如下方法,来统一处理日期格式的格式化
@InitBinder
public void handleInitBinder(WebDataBinder dataBinder){dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
}
Controller中传入参数(string类型)自动转化为Date类型
@GetMapping("testDate")
public Date processApi(Date date) {return date;
}
@ModelAttribute注解
用来预设全局参数,比如最典型的使用Spring Security时将添加当前登录的用户信息(UserDetails)作为参数。
@ModelAttribute("currentUser")
public UserDetails modelAttribute() {return (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
所有controller类中requestMapping方法都可以直接获取并使用currentUser
@PostMapping("saveSomething")
public ResponseEntity<String> saveSomeObj(@ModelAttribute("currentUser") UserDetails operator) {// 保存操作,并设置当前操作人员的ID(从UserDetails中获得)return ResponseEntity.success("ok");
}
@ControllerAdvice是如何起作用的(原理)?
DispatcherServlet中onRefresh方法是初始化ApplicationContext后的回调方法,它会调用initStrategies方法,主要更新一些servlet需要使用的对象,包括国际化处理,requestMapping,视图解析等等。
/*** This implementation calls {@link #initStrategies}.*/
@Override
protected void onRefresh(ApplicationContext context) {initStrategies(context);
}/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects.*/
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context); // 文件上传initLocaleResolver(context); // i18n国际化initThemeResolver(context); // 主题initHandlerMappings(context); // requestMappinginitHandlerAdapters(context); // adaptersinitHandlerExceptionResolvers(context); // 异常处理initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);
}
从上述代码看,如果要提供@ControllerAdvice提供的三种注解功能,从设计和实现的角度肯定是实现的代码需要放在initStrategies方法中。
@ModelAttribute和@InitBinder处理
具体来看,如果你是设计者,很显然容易想到:对于@ModelAttribute提供的参数预置和@InitBinder注解提供的预处理方法应该是放在一个方法中的,因为它们都是在进入requestMapping方法前做的操作。
如下方法是获取所有的HandlerAdapter,无非就是从BeanFactory中获取
private void initHandlerAdapters(ApplicationContext context) {this.handlerAdapters = null;if (this.detectAllHandlerAdapters) {// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.Map<String, HandlerAdapter> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerAdapters = new ArrayList<>(matchingBeans.values());// We keep HandlerAdapters in sorted order.AnnotationAwareOrderComparator.sort(this.handlerAdapters);}}else {try {HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);this.handlerAdapters = Collections.singletonList(ha);}catch (NoSuchBeanDefinitionException ex) {// Ignore, we'll add a default HandlerAdapter later.}}// Ensure we have at least some HandlerAdapters, by registering// default HandlerAdapters if no other adapters are found.if (this.handlerAdapters == null) {this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);if (logger.isTraceEnabled()) {logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +"': using default strategies from DispatcherServlet.properties");}}
}
我们要处理的是requestMapping的handlerResolver,作为设计者,就很容易出如下的结构
在RequestMappingHandlerAdapter中的afterPropertiesSet去处理advice
@Override
public void afterPropertiesSet() {// Do this first, it may add ResponseBody advice beansinitControllerAdviceCache();if (this.argumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.initBinderArgumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}
}private void initControllerAdviceCache() {if (getApplicationContext() == null) {return;}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}// 缓存所有modelAttribute注解方法Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);if (!attrMethods.isEmpty()) {this.modelAttributeAdviceCache.put(adviceBean, attrMethods);}// 缓存所有initBinder注解方法Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);if (!binderMethods.isEmpty()) {this.initBinderAdviceCache.put(adviceBean, binderMethods);}if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);}}if (!requestResponseBodyAdviceBeans.isEmpty()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}
}
@ExceptionHandler处理
@ExceptionHandler显然是在上述initHandlerExceptionResolvers(context)方法中。
同样的,从BeanFactory中获取HandlerExceptionResolver
/*** Initialize the HandlerExceptionResolver used by this class.* <p>If no bean is defined with the given name in the BeanFactory for this namespace,* we default to no exception resolver.*/
private void initHandlerExceptionResolvers(ApplicationContext context) {this.handlerExceptionResolvers = null;if (this.detectAllHandlerExceptionResolvers) {// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());// We keep HandlerExceptionResolvers in sorted order.AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);}}else {try {HandlerExceptionResolver her =context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);this.handlerExceptionResolvers = Collections.singletonList(her);}catch (NoSuchBeanDefinitionException ex) {// Ignore, no HandlerExceptionResolver is fine too.}}// Ensure we have at least some HandlerExceptionResolvers, by registering// default HandlerExceptionResolvers if no other resolvers are found.if (this.handlerExceptionResolvers == null) {this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);if (logger.isTraceEnabled()) {logger.trace("No HandlerExceptionResolvers declared in servlet '" + getServletName() +"': using default strategies from DispatcherServlet.properties");}}
}
我们很容易找到ExceptionHandlerExceptionResolver
同样的在afterPropertiesSet去处理advice
@Override
public void afterPropertiesSet() {// Do this first, it may add ResponseBodyAdvice beansinitExceptionHandlerAdviceCache();if (this.argumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}
}private void initExceptionHandlerAdviceCache() {if (getApplicationContext() == null) {return;}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);if (resolver.hasExceptionMappings()) {this.exceptionHandlerAdviceCache.put(adviceBean, resolver);}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {this.responseBodyAdvice.add(adviceBean);}}
}
示例源码
https://download.csdn.net/download/DeveloperFire/87554658
推荐阅读
Java面试系列-MySQL
JAVA面试汇总(精选系列)
相关文章:
SpringBoot接口 - 如何统一异常处理
SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?为什么要优雅的处理异常如果我们不统一的处理异常,经常会在controller层有大量的异常…...
如何使用Python进行数据可视化
数据可视化是一种将数据呈现为图形或图表的技术,它有助于理解和发现数据中的模式和趋势。Python是一种流行的编程语言,有很多库可以帮助我们进行数据可视化。在本文中,我们将介绍使用Python进行数据可视化的基本步骤。 第一步:导…...
vue -- 自定义指令钩子函数补充 自定义过滤器filter参数
自定义指令补充 自定义指令通过钩子函数的形式来实现自定义的功能 这里是几个常用的钩子函数以及它的方法: bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。 inserted:被绑定元素插…...
Qt不会操作?Qt原理不知道? | Qt详细讲解
文章目录Qt界面开发必备知识UI界面与控件类型介绍Qt设计器原理控件类型的介绍信号与槽机制处理常用控件创建与设置常见展示型控件创建与设置常见动作型控件创建与设置常见输入型控件创建与设置常见列表控件创建于设置Qt中对象树的介绍项目源码结构刨析.pro.hmain.cpp.cppQt界面…...
LeetCode-面试题 17.05. 字母与数字【前缀和,哈希表】
LeetCode-面试题 17.05. 字母与数字【前缀和,哈希表】题目描述:解题思路一:前缀和。数字为-1,字母为1。我们需要找到的子数组是前缀和之差为0的,例如s[right]-s[left]0,那么s[right]s[left],变为…...
华为OD机试题 - 叠放书籍(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:叠放书籍题目输入输出示例一输入输出Code解题思路版权说明华为O…...
【数据库概论】第十一章 数据库并发控制
第十一章 并发控制 在多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务并行运行,这就是同时并发方式。当多个用户并发存取数据库时会产生多个事务同时存取同一事务的情况,如果…...
Nginx配置实例-反向代理案例二
实现效果:使用nginx反向代理,根据访问的路径跳转到不同端口服务 nginx监听端口为9000, 访问 http://127.0.0.1:9000/edu/ 直接跳转到127.0.0.1:8080 访问 http://127.0.0.1:9000/vod/ 直接跳转到127.0.0.1:8081 一、准备工作 1. 准备两个tom…...
HTML 字符集
为了正确显示 HTML 页面,Web 浏览器必须知道要使用哪个字符集。 从 ASCII 到 UTF-8 ASCII 是第一个字符编码标准。ASCII 定义了 128 种可以在互联网上使用的字符:数字(0-9)、英文字母(A-Z)和一些特殊字符…...
【C语言】每日刷题 —— 牛客语法篇(3)
前言 大家好,继续更新专栏c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大肠9的博客…...
基于Vue3和element-plus实现一个完整的登录功能
先看一下最终要实现的效果:登录页面:注册页面:(1)引入element-plus组件库引入组件库的方式有好多种,在这里我就在main.js全局引入了.npm i element-plus -Smain.js中代码:import { createApp } from "vue"; //element-plus import ElementPlus from "element-pl…...
【java】Java 中泛型的实现原理
文章目录前序1. 泛型1.1 泛型方法1.2 泛型类1.3 泛型接口2. 泛型的基本原理3. 小结前序 泛型是 Java 开发中常用的技术,了解泛型的几种形式和实现泛型的基本原理,有助于写出更优质的代码。本文总结了 Java 泛型的三种形式以及泛型实现原理。 1. 泛型 …...
【C++提高编程】C++全栈体系(二十七)
C提高编程 第五章 STL- 常用算法 三、常用排序算法 算法简介: sort //对容器内元素进行排序random_shuffle //洗牌 指定范围内的元素随机调整次序merge // 容器元素合并,并存储到另一容器中reverse // 反转指定范围的元素 1. sort 功能描述&#…...
软考高级信息系统项目管理师系列之三十九:项目集管理
软考高级信息系统项目管理师系列之三十九:项目集管理 一、项目集管理内容二、项目集管理基础概述1.项目集定义2.项目集活动3.项目集管理三、项目集的管理过程四、项目集治理1.项目集治理概述2.项目集指导委员会的职责3.项目集治理功能五、项目集生命周期1.项目集生命周期三个阶…...
44-Golang中的channel
Golang中的channel为什么要使用channelchannel的介绍channel的基本使用定义/声明channel管道的遍历和关闭channel的关闭channel的遍历goroutine和channel结合应用实例1应用实例2案例注意事项为什么要使用channel 前面使用全局变量加锁同步来解决goroutine的通讯,但…...
80/20法则
80/20法则(The 80/20 Rule)又称为帕累托法则(Pareto Principle)、二八定律、帕累托定律、最省力法则、不平衡原则、犹太法则、马特莱法则等一、什么是80/20法则80/20法则(The 80/20 Rule),又称为帕累托法则…...
计算机网络高频面试题(四)
一、什么是计算机网络 是一个将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统 按分布范围,计算机网络里有局域网LAN和广域网WAN, 其中局域网的代表以太网,以及这…...
[计算机组成原理(唐朔飞 第2版)]第三章 系统总线(学习复习笔记)
3.1 总线的基本概念 计算机系统的五大部件之间的互连方式有两种 各部件之间使用单独的连线,称为分散连接将各部件连到一组公共信息传输线上,称为总线连接 总线是连接多个部件的信息传输线,是各部件共享的传输介质。 当多个部件与总线相连时&…...
华为OD机试题 - 计算堆栈中的剩余数字(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:计算堆栈中的剩余数字题目输入输出描述示例一输入输出说明示例二…...
VB实现点爆炸效果
需在窗体放置以下 4 个控件,所有控件不用设置任何属性,均采用默认设置: ’ Picture1,Command1,Check1,Timer1 Option Explicit Dim I Dim ctD() As tyD, ctDs As Long, ctR As Single Private Type tyD x…...
ICG-alkyne,吲哚菁绿-炔基结构式,实验室科研试剂,CAS号:1622335-41-4
ICG-alkyne,吲哚菁绿-炔基 中文名称:吲哚菁绿-炔基 CAS号:1622335-41-4 英文名称:ICG-alkyne 英文别名:ICG-alk 性状:绿色粉末 化学式:C48H53N3O4S 分子量:768.03 溶剂:溶于…...
【并发编程】volatile的原理我好像又懂了
文章目录优秀引用1、概述2、可见性保证2.1、什么是可见性2.2、例子举证2.3、结果解析3、有序性保证3.1、什么是有序性3.2、什么是重排序3.3、例子举证4、无法保证原子性4.1、什么是原子性4.2、例子举证5、内存屏障5.1、什么是内存屏障5.2、不同内存屏障的作用6、volatile和sync…...
【已更新实例】Java网络爬虫-HttpClient工具类
关于用Java进行爬虫的资料网上实在少之又少,但作为以一名对Java刚刚初窥门径建立好兴趣的学生怎么能静得下心用新学的Python去写,毕竟Java是世界上最好的语言嘛 (狗头)关于Java爬虫最受欢迎的一个框架Jsoup常常搭配HttpClient来使用,因为Jsou…...
7.2 向量的坐标
🙌作者简介:数学与计算机科学学院出身、在职高校高等数学专任教师,分享学习经验、生活、 努力成为像代码一样有逻辑的人! 🌙个人主页:阿芒的主页 ⭐ 高等数学专栏介绍:本专栏系统地梳理高等数学…...
公式编写1000问21-22
21.问: 求助——(周,日,60分钟,30分钟)MACD同时向上的公式怎么表达 答(知无不言): z:“macd.dea#week”; r:“macd.dea#day”; f:“macd.dea#min60”; f1:“macd.dea#min30”; rz:“macd.dea##week”; rr:“macd.dea##day”; rf:“…...
1041 考试座位号
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试…...
2023年3月北京/广州/杭州/深圳数据治理工程师认证DAMA-CDGA/CDGP
DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…...
【AICG】2、扩散模型 | 到底什么是扩散模型?
文章目录一、什么是扩散模型二、扩散模型相关定义2.1 符号和定义2.2 问题规范化三、可以提升的点参考论文:A Survey on Generative Diffusion Model github:https://github.com/chq1155/A-Survey-on-Generative-Diffusion-Model 一、什么是扩散模型 已…...
高等数学——多元函数微分学
文章目录多元函数微分学多元函数的极限多元函数的连续性偏导数定义高阶偏导数全微分定义全微分存在的必要条件全微分存在的充分条件多元函数的微分法复合函数微分法隐函数微分法多元函数的极值与最值无约束极值条件极值及拉格朗日乘数法最大值最小值二重积分概念性质计算利用直…...
一文打通Sleuth+Zipkin 服务链路追踪
1、为什么用 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。主要体现在,一个请求可能需要…...
织梦cms可以做淘宝客网站么/美国搜索引擎
1352 集合计数基准时间限制:1秒 空间限制:131072KB 分值:20难度:3级算法题收藏关注给出N个固定集合{1,N},{2,N-1},{3,N-2},...,{N-1,2},{N,1}.求出有多少个集合满足:第一个元素是A的倍数且第二…...
网站建设的pest分析/营销推广的工具有哪些
概况: 包字节实现了操作字节切片的函数。它类似于琴弦包的设施。 函数: func Compare(a, b []byte) intfunc Contains(b, subslice []byte) boolfunc ContainsAny(b []byte, chars string) boolfunc ContainsRune(b []byte, r rune) boolfunc Count(s, s…...
pis粉丝做的网站/百度电脑版下载
2019独角兽企业重金招聘Python工程师标准>>> 1. 使用 synchronized 关键字,代码如下 synchronized(anObject) { value map.get(key);} 2、使用 JDK1.5提供的锁(java.util.concurrent.locks.Lock)。代码如下 lock.lock(); value…...
日照 网站 建设/网页链接制作生成
由于工作需要,我要实现web表单的自动提交功能。最近网站改版在线编辑器采用了KindEditor,用原来的软件不能继续工作了,经过一周努力,终于实了再次自动提交上报的功能,现在总结记录如下。 一、原来网站提交的方式&#…...
民企厂房建设招标网站/网站建站推广
前言 这一次,我围绕Hello World来展开Zend虚拟机的执行过程。Hello World的PHP版本:<?phpecho Hello World;?>前一篇文章聊到的词法分析阶段就会把上边的脚本分析出一个Token序列:我们得到一个Token序列:T_OPEN_TAG, T_ECHO, T_CONST…...
网站建设的步骤图/中国最新消息今天
这篇文章也是基于知乎的一个答案。因为前天蛋疼写了个99行蛋疼版2048,所以一时兴起在知乎上搜了搜2048,结果发现了这个问题。看了看,票数最高的两个答案都是错的,所以自己推导了一下。2048的玩法就不赘述了,先来看看相…...