SpringMVC(三)

十、攔截器

1、攔截器的配置

SpringMVC中的攔截器用于攔截控制器方法的執行

SpringMVC中的攔截器需要實現HandlerInterceptor

SpringMVC的攔截器必須在SpringMVC的配置文件中進行配置:

<bean class="com.atguigu.interceptor.FirstInterceptor"></bean>
<ref bean="firstInterceptor"></ref>
<!-- 以上兩種配置方式都是對DispatcherServlet所處理的所有的請求進行攔截 -->
<mvc:interceptor><mvc:mapping path="/**"/><mvc:exclude-mapping path="/testRequestEntity"/><ref bean="firstInterceptor"></ref>
</mvc:interceptor>
<!-- 以上配置方式可以通過ref或bean標簽設置攔截器,通過mvc:mapping設置需要攔截的請求,通過mvc:exclude-mapping設置需要排除的請求,即不需要攔截的請求
-->

2、攔截器的三個抽象方法

SpringMVC中的攔截器有三個抽象方法:

preHandle:控制器方法執行之前執行preHandle(),其boolean類型的返回值表示是否攔截或放行,返回true為放行,即調用控制器方法;返回false表示攔截,即不調用控制器方法

postHandle:控制器方法執行之后執行postHandle()

afterComplation:處理完視圖和模型數據,渲染視圖完畢之后執行afterComplation()

3、多個攔截器的執行順序

a>若每個攔截器的preHandle()都返回true

此時多個攔截器的執行順序和攔截器在SpringMVC的配置文件的配置順序有關:

preHandle()會按照配置的順序執行,而postHandle()和afterComplation()會按照配置的反序執行

b>若某個攔截器的preHandle()返回了false

preHandle()返回false和它之前的攔截器的preHandle()都會執行,postHandle()都不執行,返回false的攔截器之前的攔截器的afterComplation()會執行

十一、異常處理器

1、基于配置的異常處理

SpringMVC提供了一個處理控制器方法執行過程中所出現的異常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的實現類有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定義的異常處理器SimpleMappingExceptionResolver,使用方式:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><!--properties的鍵表示處理器方法執行過程中出現的異常properties的值表示若出現指定異常時,設置一個新的視圖名稱,跳轉到指定頁面--><prop key="java.lang.ArithmeticException">error</prop></props></property><!--exceptionAttribute屬性設置一個屬性名,將出現的異常信息在請求域中進行共享--><property name="exceptionAttribute" value="ex"></property>
</bean>

2、基于注解的異常處理

//@ControllerAdvice將當前類標識為異常處理的組件
@ControllerAdvice
public class ExceptionController {//@ExceptionHandler用于設置所標識方法處理的異常@ExceptionHandler(ArithmeticException.class)//ex表示當前請求處理中出現的異常對象public String handleArithmeticException(Exception ex, Model model){model.addAttribute("ex", ex);return "error";}}

十二、注解配置SpringMVC

使用配置類和注解代替web.xml和SpringMVC配置文件的功能

1、創建初始化類,代替web.xml

在Servlet3.0環境中,容器會在類路徑中查找實現javax.servlet.ServletContainerInitializer接口的類,如果找到的話就用它來配置Servlet容器。
Spring提供了這個接口的實現,名為SpringServletContainerInitializer,這個類反過來又會查找實現WebApplicationInitializer的類并將配置的任務交給它們來完成。Spring3.2引入了一個便利的WebApplicationInitializer基礎實現,名為AbstractAnnotationConfigDispatcherServletInitializer,當我們的類擴展了AbstractAnnotationConfigDispatcherServletInitializer并將其部署到Servlet3.0容器的時候,容器會自動發現它,并用它來配置Servlet上下文。

public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {/*** 指定spring的配置類* @return*/@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}/*** 指定SpringMVC的配置類* @return*/@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};}/*** 指定DispatcherServlet的映射規則,即url-pattern* @return*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}/*** 添加過濾器* @return*/@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();encodingFilter.setEncoding("UTF-8");encodingFilter.setForceRequestEncoding(true);HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();return new Filter[]{encodingFilter, hiddenHttpMethodFilter};}
}

2、創建SpringConfig配置類,代替spring的配置文件

@Configuration
public class SpringConfig {//ssm整合之后,spring的配置信息寫在此類中
}

3、創建WebConfig配置類,代替SpringMVC的配置文件

@Configuration
//掃描組件
@ComponentScan("com.atguigu.mvc.controller")
//開啟MVC注解驅動
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {//使用默認的servlet處理靜態資源@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}//配置文件上傳解析器@Beanpublic CommonsMultipartResolver multipartResolver(){return new CommonsMultipartResolver();}//配置攔截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {FirstInterceptor firstInterceptor = new FirstInterceptor();registry.addInterceptor(firstInterceptor).addPathPatterns("/**");}//配置視圖控制/*@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("index");}*///配置異常映射/*@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();Properties prop = new Properties();prop.setProperty("java.lang.ArithmeticException", "error");//設置異常映射exceptionResolver.setExceptionMappings(prop);//設置共享異常信息的鍵exceptionResolver.setExceptionAttribute("ex");resolvers.add(exceptionResolver);}*///配置生成模板解析器@Beanpublic ITemplateResolver templateResolver() {WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();// ServletContextTemplateResolver需要一個ServletContext作為構造參數,可通過WebApplicationContext 的方法獲得ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());templateResolver.setPrefix("/WEB-INF/templates/");templateResolver.setSuffix(".html");templateResolver.setCharacterEncoding("UTF-8");templateResolver.setTemplateMode(TemplateMode.HTML);return templateResolver;}//生成模板引擎并為模板引擎注入模板解析器@Beanpublic SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver);return templateEngine;}//生成視圖解析器并未解析器注入模板引擎@Beanpublic ViewResolver viewResolver(SpringTemplateEngine templateEngine) {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setCharacterEncoding("UTF-8");viewResolver.setTemplateEngine(templateEngine);return viewResolver;}}

4、測試功能

@RequestMapping("/")
public String index(){return "index";
}

十三、SpringMVC執行流程

1、SpringMVC常用組件

  • DispatcherServlet:前端控制器,不需要工程師開發,由框架提供

作用:統一處理請求和響應,整個流程控制的中心,由它調用其它組件處理用戶的請求

  • HandlerMapping:處理器映射器,不需要工程師開發,由框架提供

作用:根據請求的url、method等信息查找Handler,即控制器方法

  • Handler:處理器,需要工程師開發

作用:在DispatcherServlet的控制下Handler對具體的用戶請求進行處理

  • HandlerAdapter:處理器適配器,不需要工程師開發,由框架提供

作用:通過HandlerAdapter對處理器(控制器方法)進行執行

  • ViewResolver:視圖解析器,不需要工程師開發,由框架提供

作用:進行視圖解析,得到相應的視圖,例如:ThymeleafView、InternalResourceView、RedirectView

  • View:視圖

作用:將模型數據通過頁面展示給用戶

2、DispatcherServlet初始化過程

DispatcherServlet 本質上是一個 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏觀上是 Servlet 生命周期來進行調度。

在這里插入圖片描述

a>初始化WebApplicationContext

所在類:org.springframework.web.servlet.FrameworkServlet

protected WebApplicationContext initWebApplicationContext() {WebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// A context instance was injected at construction time -> use itwac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {// The context has not yet been refreshed -> provide services such as// setting the parent context, setting the application context id, etcif (cwac.getParent() == null) {// The context instance was injected without an explicit parent -> set// the root application context (if any; may be null) as the parentcwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac == null) {// No context instance was injected at construction time -> see if one// has been registered in the servlet context. If one exists, it is assumed// that the parent context (if any) has already been set and that the// user has performed any initialization such as setting the context idwac = findWebApplicationContext();}if (wac == null) {// No context instance is defined for this servlet -> create a local one// 創建WebApplicationContextwac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {// Either the context is not a ConfigurableApplicationContext with refresh// support or the context injected at construction time had already been// refreshed -> trigger initial onRefresh manually here.synchronized (this.onRefreshMonitor) {// 刷新WebApplicationContextonRefresh(wac);}}if (this.publishContext) {// Publish the context as a servlet context attribute.// 將IOC容器在應用域共享String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);}return wac;
}
b>創建WebApplicationContext

所在類:org.springframework.web.servlet.FrameworkServlet

protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {Class<?> contextClass = getContextClass();if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +"': custom WebApplicationContext class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}// 通過反射創建 IOC 容器對象ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setEnvironment(getEnvironment());// 設置父容器wac.setParent(parent);String configLocation = getContextConfigLocation();if (configLocation != null) {wac.setConfigLocation(configLocation);}configureAndRefreshWebApplicationContext(wac);return wac;
}
c>DispatcherServlet初始化策略

FrameworkServlet創建WebApplicationContext后,刷新容器,調用onRefresh(wac),此方法在DispatcherServlet中進行了重寫,調用了initStrategies(context)方法,初始化策略,即初始化DispatcherServlet的各個組件

所在類:org.springframework.web.servlet.DispatcherServlet

protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);
}

3、DispatcherServlet調用組件處理請求

a>processRequest()

FrameworkServlet重寫HttpServlet中的service()和doXxx(),這些方法中調用了processRequest(request, response)

所在類:org.springframework.web.servlet.FrameworkServlet

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {// 執行服務,doService()是一個抽象方法,在DispatcherServlet中進行了重寫doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}
}
b>doService()

所在類:org.springframework.web.servlet.DispatcherServlet

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {logRequest(request);// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the include.Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}RequestPath requestPath = null;if (this.parseRequestPath && !ServletRequestPathUtils.hasParsedRequestPath(request)) {requestPath = ServletRequestPathUtils.parseAndCache(request);}try {// 處理請求和響應doDispatch(request, response);}finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}if (requestPath != null) {ServletRequestPathUtils.clearParsedRequestPath(request);}}
}
c>doDispatch()

所在類:org.springframework.web.servlet.DispatcherServlet

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request./*mappedHandler:調用鏈包含handler、interceptorList、interceptorIndexhandler:瀏覽器發送的請求所匹配的控制器方法interceptorList:處理控制器方法的所有攔截器集合interceptorIndex:攔截器索引,控制攔截器afterCompletion()的執行*/mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.// 通過控制器方法創建相應的處理器適配器,調用所對應的控制器方法HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// 調用攔截器的preHandle()if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.// 由處理器適配器調用具體的控制器方法,最終獲得ModelAndView對象mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);// 調用攔截器的postHandle()mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException = new NestedServletException("Handler dispatch failed", err);}// 后續處理:處理模型數據和渲染視圖processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}
}
d>processDispatchResult()
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {boolean errorView = false;if (exception != null) {if (exception instanceof ModelAndViewDefiningException) {logger.debug("ModelAndViewDefiningException encountered", exception);mv = ((ModelAndViewDefiningException) exception).getModelAndView();}else {Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);mv = processHandlerException(request, response, handler, exception);errorView = (mv != null);}}// Did the handler return a view to render?if (mv != null && !mv.wasCleared()) {// 處理模型數據和渲染視圖render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isTraceEnabled()) {logger.trace("No view rendering, null ModelAndView returned.");}}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Concurrent handling started during a forwardreturn;}if (mappedHandler != null) {// Exception (if any) is already handled..// 調用攔截器的afterCompletion()mappedHandler.triggerAfterCompletion(request, response, null);}
}

4、SpringMVC的執行流程

  1. 用戶向服務器發送請求,請求被SpringMVC 前端控制器 DispatcherServlet捕獲。

  2. DispatcherServlet對請求URL進行解析,得到請求資源標識符(URI),判斷請求URI對應的映射:

a) 不存在

i. 再判斷是否配置了mvc:default-servlet-handler

ii. 如果沒配置,則控制臺報映射查找不到,客戶端展示404錯誤

在這里插入圖片描述

在這里插入圖片描述

iii. 如果有配置,則訪問目標資源(一般為靜態資源,如:JS,CSS,HTML),找不到客戶端也會展示404錯誤

在這里插入圖片描述

在這里插入圖片描述

b) 存在則執行下面的流程

  1. 根據該URI,調用HandlerMapping獲得該Handler配置的所有相關的對象(包括Handler對象以及Handler對象對應的攔截器),最后以HandlerExecutionChain執行鏈對象的形式返回。

  2. DispatcherServlet 根據獲得的Handler,選擇一個合適的HandlerAdapter。

  3. 如果成功獲得HandlerAdapter,此時將開始執行攔截器的preHandler(…)方法【正向】

  4. 提取Request中的模型數據,填充Handler入參,開始執行Handler(Controller)方法,處理請求。在填充Handler的入參過程中,根據你的配置,Spring將幫你做一些額外的工作:

a) HttpMessageConveter: 將請求消息(如Json、xml等數據)轉換成一個對象,將對象轉換為指定的響應信息

b) 數據轉換:對請求消息進行數據轉換。如String轉換成Integer、Double等

c) 數據格式化:對請求消息進行數據格式化。 如將字符串轉換成格式化數字或格式化日期等

d) 數據驗證: 驗證數據的有效性(長度、格式等),驗證結果存儲到BindingResult或Error中

  1. Handler執行完成后,向DispatcherServlet 返回一個ModelAndView對象。

  2. 此時將開始執行攔截器的postHandle(…)方法【逆向】。

  3. 根據返回的ModelAndView(此時會判斷是否存在異常:如果存在異常,則執行HandlerExceptionResolver進行異常處理)選擇一個適合的ViewResolver進行視圖解析,根據Model和View,來渲染視圖。

  4. 渲染視圖完畢執行攔截器的afterCompletion(…)方法【逆向】。

  5. 將渲染結果返回給客戶端。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164681.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164681.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164681.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

constexpt

constexpt constexpt是C11引入的新的關鍵字&#xff0c;它用于在編譯時而非運行時計算函數或變量的值。這個特性對于提高程序效率和優化代非常有用。 編譯時常量和運行時常量 編譯時常量&#xff08;Compile-time Constants&#xff09;和運行時常量&#xff08;Runtime Con…

8年經驗之談 —— 如何使用自動化工具編寫測試用例?

以下為作者觀點&#xff0c;僅供參考&#xff1a; 在快速變化的軟件開發領域&#xff0c;保證應用程序的可靠性和質量至關重要。隨著應用程序復雜性和規模的不斷增加&#xff0c;僅手動測試無法滿足行業需求。 這就是測試自動化發揮作用的地方&#xff0c;它使軟件測試人員能…

leetcode做題筆記1410. HTML 實體解析器

「HTML 實體解析器」 是一種特殊的解析器&#xff0c;它將 HTML 代碼作為輸入&#xff0c;并用字符本身替換掉所有這些特殊的字符實體。 HTML 里這些特殊字符和它們對應的字符實體包括&#xff1a; 雙引號&#xff1a;字符實體為 &quot; &#xff0c;對應的字符是 "…

python appium 官網下載

找了半天吐了 https://github.com/appium/appium-desktop/releases/tag/v1.22.3-4

Hibernate批量處理數據

概念&#xff1a; 批量處理數據是指在一個事務場景中處理大量數據。 在應用程序中難以避免進行批量操作&#xff0c;Hibernate提供了以下方式進行批量處理數據&#xff1a; (1)使用HQL進行批量操作 數據庫層面 executeUpdate() (2)使用JDBC API進行批量操作 數據庫層面 …

Vue學習筆記-Object.defineproperty函數

文章目錄 前文提要Object.defineProperty作用Object.defineProperty參數使用例圖getter&#xff0c;也就是get函數setter&#xff0c;也就是set函數 前文提要 本人僅做個人學習記錄&#xff0c;如有錯誤&#xff0c;請多包涵 Object.defineProperty作用 當在js中聲明了一個變…

王道p150 20.將給定的表達式樹轉化為等價的中綴表達式(通過括號反應操作符的計算次序)

本題代碼如下 void btreetoexp(tree t, char deep) {if (t NULL)return;else if (t->lchild NULL && t->rchild NULL)printf("%c", t->data);//輸出操作數&#xff0c;不加括號else {if (deep > 1)printf("(");btreetoexp(t->l…

Rust語言入門教程(二) - 變量與作用域

變量與作用域 變量的聲明與初始化 Rust的基本語法格式如下&#xff1a; fn main(){let bunnies 2; }語句以分號結尾&#xff0c;用花括號包含語句塊。 Rust的語法其實借鑒了很多其他的語言&#xff0c;比如C語言和Python&#xff0c; 所以變量定義的格式看起來也跟很多我們…

shell 腳本的函數和數組

函數 —— 封裝的一個公式&#xff1a;sin、cos、tan —— 函數為腳本的別名 —— 函數就是一個功能模塊&#xff0c;在函數中寫執行的命令即可&#xff1b;使用函數可以避免代碼重復&#xff0c;增加可讀性&#xff0c;簡化腳本&#xff0c;使用函數可以將大的工程分割為若…

Vue中動態class方法

1.方法一&#xff1a;只需要展示一個class樣式&#xff0c;但是動態取值 <div :class"aaa"></div>data:{return () {aaa:colorRed} }.colorRed {color: red; } 2.方法二&#xff1a;表達式判斷是否展示class里面的樣式 <div :class"{colorRed…

函數與數組

一.函數 1、函數的作用 定義較為復雜的但是需要重復使用的內容&#xff0c;以便再次使用&#xff0c;可以直接調用&#xff0c;節約時間&#xff0c;提高效率。 語句塊定義成函數約等于別名&#xff0c;定義函數&#xff0c;再引用函數。 封裝的可重復利用的具有特定功能的…

python+django高校科研項目管理系統2u3mx

高校科研項目管理系統采用擬開發的高校科研項目管理系統通過測試,確保在最大負載的情況下穩定運轉,各個模塊工作正常,具有較高的可用性。系統整體界面簡潔美觀,用戶使用簡單,滿足用戶需要。在因特網發展迅猛的當今社會,高校科研項目管理系統必然會成為在數字信息化建設的一個重…

Linux 查看 CPU 信息相關命令

目錄 lscpu top htop lscpu lscpu 命令是用于顯示有關 CPU 架構的信息&#xff0c;而不是用于實時監視 CPU 負載。它提供有關 CPU 類型、核心數、線程數、架構等的詳細信息。 lscpu top 命令會顯示系統的實時狀態&#xff0c;包括 CPU 使用率、內存使用率等。按下鍵盤上的…

一文詳解Vue生命周期

Vue是一種流行的用于構建用戶界面的漸進式JavaScript框架。Vue框架在開發過程中&#xff0c;特別強調對生命周期的理解和管理。通過使用生命周期鉤子函數&#xff0c;開發者能夠精確地控制Vue實例的創建、掛載、更新以及銷毀過程。本文將對Vue的生命周期進行詳細的介紹&#xf…

YOLOv8訓練自己的目標檢測數據集

YOLOv8訓練自己的目標檢測數據集 目錄標題 源碼下載環境配置安裝包訓練自己的數據集數據集文件格式數據集文件配置超參數文件配置訓練數據集命令行訓練腳本.py文件訓練 進行detect顯示detect的效果 源碼下載 YOLOv8官方的GitHub代碼&#xff0c;同時上面也有基礎環境的配置要…

IntelliJ IDEA 16創建Web項目

首先要理解一個概念&#xff1a;在IntelliJ IDEA中“new Project”相當于eclipse中的工作空間&#xff08;Workspace&#xff09;&#xff0c;而“new Module”相當于eclipse中的工程&#xff08;Project&#xff09;。以下均采用Intellij的說法&#xff0c;請自行對照轉換理解…

Maven倉庫清除remote.repositories、lastUpdated、sha1腳本

Maven倉庫清除remote.repositories、lastUpdated、sha1腳本 1. 腳本功能 清除本地maven倉庫的_remote.repositories、sha1、lastUpdated的文件 2. 腳本內容 set REPOSITORY_PATH%cd% rem 搜索中... for /f "delims" %%i in (dir /b /s "%REPOSITORY_PATH%\*…

Java 關鍵字:synchronized詳解

synchronized詳解 基本使用源碼解析常見面試題好書推薦 基本使用 Java中的synchronized關鍵字用于在多線程環境下確保數據同步。它可以用來修飾方法和代碼塊 當一個線程訪問一個對象的synchronized方法或代碼塊時&#xff0c;其他線程將無法訪問該對象的其他synchronized方法或…

【愚公系列】2023年11月 Java教學課程 188-SpringCloud(Feign遠程調用)

&#x1f3c6; 作者簡介&#xff0c;愚公搬代碼 &#x1f3c6;《頭銜》&#xff1a;華為云特約編輯&#xff0c;華為云云享專家&#xff0c;華為開發者專家&#xff0c;華為產品云測專家&#xff0c;CSDN博客專家&#xff0c;阿里云專家博主&#xff0c;阿里云簽約作者&#xf…

如何通過寶塔面板搭建一個本地MySQL數據庫服務并實現遠程訪問

寶塔安裝MySQL數據庫&#xff0c;并內網穿透實現公網遠程訪問 文章目錄 寶塔安裝MySQL數據庫&#xff0c;并內網穿透實現公網遠程訪問前言1.Mysql服務安裝2.創建數據庫3.安裝cpolar3.2 創建HTTP隧道 4.遠程連接5.固定TCP地址5.1 保留一個固定的公網TCP端口地址5.2 配置固定公網…