主頁 > 後端開發 > Spring MVC官方檔案學習筆記(二)之DispatcherServlet

Spring MVC官方檔案學習筆記(二)之DispatcherServlet

2023-06-01 07:37:57 後端開發

1.DispatcherServlet入門

(1) Spring MVC是以前端控制器模式(即圍繞著一個中央的Servelt, DispatcherServlet)進行設計的,這個DispatcherServlet為請求的處理提供了一個共用的演算法,即它都會將實際的請求處理作業委托給那些可配置的組件進行執行,說白了,DispatcherServlet的作用就是進行統一調度,并控制請求的處理流程,和其他的Servlet一樣,DispatcherServlet需要根據Servlet規范,使用基于Java的配置或在web.xml中進行宣告,與此同時,DispatcherServlet會使用Spring相關配置來發現它在請求映射、視圖決議、例外處理等方面所需要的組件,而實際的作業也會交由這些組件進行執行,下面列出了注冊DispatcherServlet的一些方式

@Configuration
@ComponentScan("cn.example.springmvc.boke")
public class WebConfig {
}

//使用基于Java的配置,注冊并初始化一個DispatcherServlet
public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //宣告一個Spring-web容器
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(WebConfig.class);

        //創建并注冊DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ctx);
        //動態的添加Servlet
        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet", servlet);
        registration.setLoadOnStartup(1);
        //指定由DispatcherServlet攔截所有請求(包括靜態資源,但不攔截.jsp)
        registration.addMapping("/");
    }
}

上述是基于Java的配置,我們還可以基于web.xml來配置DispatcherServlet,如下

<web-app ....>
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

(2) 現在DispatcherServlet有了,我們還需要@Controller與@RequestMapping注解,來標注某個訪問應該由誰進行處理,如下,而到此為止,我們就已經完全不需要撰寫HttpServlet相關的內容了,可見通過DispatcherServlet幫助我們免去了冗雜的Servlet映射配置

@Controller
public class DemoController {
    @RequestMapping("/demo")
    @ResponseBody
    public String get(HttpServletRequest request) {
        return "aaa";
    }
}

啟動容器,訪問 http://localhost:8080/springmvc/demo, 頁面顯示aaa,說明訪問正常,這便是我們的第一個Spring MVC專案

2.Spring容器的層次結構

(1) 根容器與Servlet子容器

通常情況下,一個web應用中有一個唯一的WebApplicationContext容器就足夠了,但Spring還允許我們配置具有父子關系的根容器和它的Servlet子容器,來形成一個層次結構,如上圖所示,可以很清楚的看到,Spring將表示層相關的組件全部放到了子容器中,而將公共的與基礎服務有關的組件全部放到了根容器中,這樣的話,當我們需要注冊多個DispatcherServlet并共享那些基礎服務組件的時候,不必重復注冊Service和Dao了,因為每個Servlet子容器都可以從這個根容器中獲取到Service和Dao,這便是層次結構的意義

當然,Spring也支持單容器配置,如開頭中的示例那樣,此外我們可以通過繼承AbstractAnnotationConfigDispatcherServletInitializer來配置父子容器,如下

//配置父子容器,其中容器使用基于注解的配置方式
public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //配置 DispatcherServlet 攔截的路徑
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    //設定根容器的配置類
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }

    //設定子容器的配置類
    //如果不想形成父子容器,那么只需將下面這個getServletConfigClasses()方法回傳null即可
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }
}

//由于我們采用的是父子容器,因此這就要求我們撰寫父子容器的組態檔時,根容器的組態檔(RootConfig)配置非web組件的bean,而子容器的組態檔(WebConfig)配置web組件的bean,同時,也要防止同一組件在不同容器中分別注冊初始化,從而出現兩個相同bean
//根容器配置類,使用excludeFilters排除掉@Controller注解標注的類和@Configuration注解標注的類,這里之所以要排除掉@Configuration注解標注的類,是為了防止根容器掃描到子容器的配置類WebConfig
@Configuration
@ComponentScan(value = "https://www.cnblogs.com/shame11/p/cn.example.springmvc.boke",
                excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = https://www.cnblogs.com/shame11/p/Controller.class),
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)
                })
public class RootConfig {
}

//子容器配置類,使用includeFilters指定只掃描由@Controller注解標注的類
@Configuration
@ComponentScan(value ="https://www.cnblogs.com/shame11/p/cn.example.springmvc.boke",
        includeFilters = @ComponentScan.Filter(value = https://www.cnblogs.com/shame11/p/Controller.class, type = FilterType.ANNOTATION))
public class WebConfig {
}

也可以基于web.xml來配置父子容器,如下

<web-app ....>
    <!-- ContextLoaderListener用于配置根容器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 設定根容器的xml組態檔路徑 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springroot.xml</param-value>
    </context-param>

    <!-- DispatcherServlet用于配置子容器 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 設定子容器的xml組態檔路徑 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springweb.xml</param-value>
        </init-param>
    </servlet>
    
    <!-- 設定 DispatcherServlet 攔截的路徑  -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3.特殊型別的bean

(1) 前面已經提過了,DispatcherServlet會將實際的請求處理程序委托給那些特殊的組件來干,而它本身起一個統一分配與調度的作用,這些特殊的組件已經由Spring提供了默認的實作,但同時Spring也允許我們自己實作替換它們,下表列出了由 DispatcherServlet檢測到的這些特殊的Bean型別

Bean型別 說明
HandlerMapping 處理器映射器,主要就是將請求路徑(uri)映射到能處理該請求的處理器(handler),DispatcherServlet在接收到請求后,該請求會交由誰來處理?這個匹配查找的作業不是由DispatcherServlet來做的,而是交由HandlerMapping負責的,而至于Handler,我們可以把它理解為在@Controller注解所標注的類中的一個標注了@RequestMapping注解的方法,所謂的匹配本質上就是匹配@RequestMapping注解中所宣告的值罷了,注意:HandlerMapping在查找匹配到對應的Handler后,并不是直接回傳這個Handler,而是回傳這個Handler的包裝物件HandlerExecutionChain,而這個HandlerExecutionChain其實就是 Handler + 該請求所涉及到的攔截器 所組合而成的一個物件,
兩個主要的HandlerMapping實作類分別是RequestMappingHandlerMapping(標注了@RequestMapping注解的方法)和SimpleUrlHandlerMapping(若在xml中顯式的配置了請求路徑與Controller的對應關系,則會使用該處理器映射器)
HandlerAdapter 幫助 DispatcherServlet 呼叫映射匹配到的HandlerExecutionChain,換句話說,DispatcherServlet獲得HandlerExecutionChain后,它不會進行呼叫執行,而是交由HandlerAdapter來呼叫執行HandlerExecutionChain
HandlerExceptionResolver 解決例外的策略,用于定義在請求映射,引數系結或方法執行時若發生例外,該怎么處理
ViewResolver Handler方法執行后,將回傳的邏輯視圖名(通常為一個String字串)決議為真正的視圖(如.jsp 、.html等),并進行視圖渲染,渲染完成后,將視圖回傳給DispatcherServlet
LocaleResolver, LocaleContextResolver 用于決議客戶的Locale,實作國際化功能
ThemeResolver 決議你的web應用可使用的主題(theme),主題是一系列靜態資源的集合(比如說css檔案,圖片等)
MultipartResolver 專門用于處理檔案上傳
FlashMapManager 專門用于保存和管理FlashMap,而這個FlashMap是用來在重定向時傳遞引數的,因為redirect重定向是不能傳遞引數的,此時就可以借助FlashMap

4.Web MVC配置

(1) 我們可以自定義在上一節中所列出來的那些特殊的bean,DispatcherServlet會檢查它們,如果沒有,那么它將會使用DispatcherServlet.properties中所列出的默認型別的bean,如下

5.Servlet 配置

(1) 在Servlet環境中,我們可以選擇以編程式的方式或基于web.xml的方式來配置Servlet容器,在本篇開頭的位置也提到過了,如下是一個基于編程式的例子

public class IocInit implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //創建一個基于xml配置的容器
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("classpath:springmvc.xml");

        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

WebApplicationInitializer是由Spring MVC提供的一個介面,Spring MVC會確保該介面的實作類們會被正確呼叫以初始化Servlet容器,WebApplicationInitializer有一個抽象基類為AbstractDispatcherServletInitializer,通過繼承該基類可以使得注冊DispatcherServlet更加容易

(2) 除了上面的例子之外,還可以使用基于java的Spring配置,如下,前面也提到過了

public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    //創建一個基于注解配置的容器
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }
}

(3) 除此之外,還可以繼承AbstractDispatcherServletInitializer

public class IocInit extends AbstractDispatcherServletInitializer {
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("classpath:springmvc.xml");
        return cxt;
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }
}

上面列出了常見的3種創建ioc容器的方式,我們可以根據自己的需要來進行選擇

(4) AbstractDispatcherServletInitializer還提供了一種便捷的方式來創建Filter實體,并且這些Filter實體會被自動映射到DispatcherServlet上,如下

public class IocInit extends AbstractDispatcherServletInitializer {

    //...
    
    //這些Filter會被自動映射到DispatcherServlet上,并且會根據它們的型別來為其添加一個默認名稱
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
                new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}

此外,如果我們希望需要進一步的定制DispatcherServlet,我們可以重寫createDispatcherServlet方法

6.請求處理

(1) DispatcherServlet按照如下的方式來處理請求:

  • 搜索WebApplicationContext并將其作為一個屬性系結到請求中,這樣在請求的后續處理程序中我們就可以直接從請求中拿到ioc容器,如下
@Controller
public class DemoController {
    @RequestMapping("/demo")
    @ResponseBody
    public String get(HttpServletRequest httpServletRequest) {
        //從請求中獲取到WebApplicationContext,這個ioc容器被系結到了請求的DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE屬性上
        WebApplicationContext ctx = (WebApplicationContext)httpServletRequest.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
        return "aaa";
    }
}
  • Locale決議器也被系結到了請求上,以便后續處理流程中進行使用

  • Theme決議器也被系結到了請求上,以便后續處理流程中進行使用

  • 如果我們指定了multipart檔案決議器,那么Spring會檢查請求中是否含有multipart檔案,如果有,那么該請求會被包裹在一個MultipartHttpServletRequest中,以便后續處理流程中進行進一步處理

  • 針對請求搜索恰當的handler,如果搜索到的話,與該handler相關的執行鏈(HandlerExecutionChain)將會被執行,以準備渲染模型(model)

  • 如果有模型回傳,那么視圖(view)就會被渲染,否則,如果沒有模型回傳,那么視圖就不會被渲染

(2) 在WebApplicationContext中的HandlerExceptionResolver型別的bean將被用來解決請求處理程序中拋出的例外,這些例外決議器允許自定義處理例外的邏輯

(3) 我們可以在web.xml中的標簽使用標簽來添加Servlet初始化引數,這樣就能達到定制DispatcherServlet的目的,下面列出了DispatcherServlet常見的初始化引數

引數 說明
contextClass 設定web容器,該容器必須是ConfigurableWebApplicationContext的實作類,默認為XmlWebApplicationContext
contextConfigLocation 該引數值將會被傳遞至由上面contextClass指定的容器,通常用于指明組態檔(xml檔案,@Configuration注解標注的類)的路徑,容器會到指定位置加載組態檔
namespace 容器的命名空間,默認為[servlet-name]-servlet
throwExceptionIfNoHandlerFound 決定當一個請求沒有找到其對應的handler時,是否會拋出NoHandlerFoundException例外,若設定為true,則表示拋出例外,然后我們就可以用HandlerExceptionResolver來捕獲該例外,并像處理其他例外一樣進行該處理,在默認情況下,該值被設定為false,因此在默認情況下,如果一個請求沒有找到其對應的handler,那么DispatcherServlet會將回應狀態碼設定為404(NOT_FOUND)而不會引發例外,因此我們會在頁面上看到一個 "404 - 未找到" 頁面,最后注意,如果defaultServletHandling也被配置了,那么這些不正常的請求會被轉發到defaultServlet進行處理,且永遠不會出現404

具體的配置例子如下

<web-app ....>

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置容器,容器需要實作ConfigurableWebApplicationContext介面,此處我們選擇了XmlWebApplicationContext,這也是Spring的默認配置 -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.XmlWebApplicationContext</param-value>
        </init-param>

        <!-- 因為我們上面選用的是XmlWebApplicationContext,一個基于xml配置的容器,因此通過contextConfigLocation屬性來設定容器的xml組態檔路徑 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springweb.xml</param-value>
        </init-param>

        <!-- 如下是配置一個基于注解的容器 -->
<!--        <init-param>-->
<!--            <param-name>contextClass</param-name>-->
<!--            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>-->
<!--        </init-param>-->
        <!-- 因為是基于注解的容器,因此通過contextConfigLocation屬性來設定Configuration配置類的路徑 -->
<!--        <init-param>-->
<!--            <param-name>contextConfigLocation</param-name>-->
<!--            <param-value>cn.example.springmvc.boke.config.Config</param-value>-->
<!--        </init-param>-->

        <!-- 設定WebApplicationContext的命名空間 -->
        <init-param>
            <param-name>namespace</param-name>
            <param-value>app</param-value>
        </init-param>

        <!-- 注意,單單將這個值設定為true,并不會生效(即不會拋出NoHandlerFoundException例外),原因是Spring會默認加上ResourceHttpRequestHandler這個handler來進行處理,也就不會出現no handler的情況了,因此我們還需要配置spring.resources.add-mappings=false,這樣在發生no handler時才會拋出NoHandlerFoundException例外 -->
        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <!-- 設定 DispatcherServlet 攔截的路徑  -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

7.攔截器

(1) 攔截器必須實作HandlerInterceptor介面,該介面提供了3個方法,分別為

  • preHandle(..): 在handler執行之前執行

  • postHandle(..): 在handler執行之后執行

  • afterCompletion(..): 在整個請求完成后執行

preHandle方法回傳一個boolean值,通過該方法我們可以決定是繼續還是中斷執行鏈的執行,若回傳true,則執行鏈繼續執行,若回傳false,則DispatcherServlet會認為攔截器本身已經處理了該請求,因此會中斷執行鏈中其他的攔截器以及handler的執行

postHandle方法在有@ResponseBody和ResponseEntity的方法中用處不大,因為這種方法在postHandle方法執行前已經在寫入response了,等待postHandle方法執行時已經太遲了,而針對這種情況,我們可以使用ResponseBodyAdvice

8.例外

(1) 如果在請求映射處理程序中發生例外,DispatcherServlet會委托一個由HandlerExceptionResolver構成的例外處理鏈來處理這個例外,下面列出一些可用的HandlerExceptionResolver實作類

HandlerExceptionResolver 說明
SimpleMappingExceptionResolver 提供例外類名稱與例外視圖名稱之間的一個映射,即針對不同型別的例外回應不同的錯誤視圖
DefaultHandlerExceptionResolver 決議由Spring MVC引發的標準例外,并將它們映射成對應的HTTP狀態碼,它是作為“預設”使用的,如果其他HandlerExceptionResolver不能處理某些例外,最后會使用DefaultHandlerExceptionResolver來統一處理
ResponseStatusExceptionResolver 決議被@ResponseStatus注解標注的例外,并根據注解中的值將例外映射到對應的HTTP狀態碼
ExceptionHandlerExceptionResolver 通過呼叫@ControllerAdvice類或@Controller類中合適的@ExceptionHandler方法來決議例外

(2) 我們可以在容器中配置多個HandlerExceptionResolver型別的bean并根據需要設定它們的order屬性來形成一個例外處理器鏈,其中order屬性值越高,它在例外處理器鏈中的位置就越靠后,通常情況下,HandlerExceptionResolver回傳

  • 一個指向錯誤視圖的ModelAndView

  • 若例外在處理器中被處理,回傳一個空的ModelAndView

  • 若例外未被解決,則回傳null,以便讓后續的處理器嘗試解決,如果到最后例外仍未解決,則允許將例外冒泡到Servlet容器中

使用MVC Config(通過@EnableWebMvc注解)后,會自動的向容器中添加Spring MVC例外,由@ResponseStatus注解標注的例外等例外的處理器,我們可以對它們進行替換

(3) 如果一個例外沒有被任何HandlerExceptionResolver處理或者請求的http回應被設定為錯誤狀態(即4xx,5xx),那么Servlet容器使用HTML來渲染一個默認的錯誤頁面,而為了自定義容器的默認錯誤頁面,我們可以在web.xml中配置錯誤頁面映射url,如下

<error-page>
    <location>/error</location>
</error-page>

當配置好錯誤頁面映射url后,如果此時有一個例外沒有被任何HandlerExceptionResolver處理或者請求的http回應被設定為錯誤狀態,那么Servlet容器將會請求我們所配置的這個url,此時,我們就可以回傳一個自定義的錯誤視圖或像下面這樣直接回傳一個字串

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

9. view,locale,theme和logging這四節的內容略過,如果有需要可查看官方檔案

10. Multipart決議器

(1) org.springframework.web.multipart包中的MultipartResolver可用于決議multipart型別(例如:檔案上傳)的請求,為了使用Multipart決議器,我們需要配置一個MultipartResolver型別的bean,并且這個bean的名稱必須是multipartResolver,配置好之后,DispatcherServlet會檢測到它并將其應用于后續的請求,當我們接收到一個型別為multipart/form-data的post請求時,Multipart決議器會決議請求內容并將當前這個HttpServletRequest包裝成MultipartHttpServletRequest以便訪問決議的內容,Spring MVC已為我們提供了兩個MultipartResolver的實作類,如下

  • CommonsMultipartResolver:基于Apache Commons FileUpload的MultipartResolver實作類,為了使用它,需要添加commons-fileupload依賴

  • StandardServletMultipartResolver:基于Servlet 3.0 multipart請求決議的MultipartResolver實作類,為了使用它,我們需要在<web.xml/>或Servlet registration中進行一些配置:

<!-- 在web.xml的<servlet/>標簽中添加<multipart-config/>標簽,配置上傳檔案的大小等資訊 -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <multipart-config>
        <location>/</location>
        <max-file-size>2097152</max-file-size>
        <max-request-size>419304</max-request-size>
    </multipart-config>
</servlet>

也可在Servlet registration中進行配置

public class IocInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }

    //使用ServletRegistration配置上傳檔案大小等資訊
    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setMultipartConfig(new MultipartConfigElement("/", 2097152, 419304, 0));
    }
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553935.html

標籤:Java

上一篇:別再滿屏找日志了!推薦一款 IDEA 日志管理插件,看日志輕松多了!

下一篇:返回列表

標籤雲
其他(160069) Python(38189) JavaScript(25469) Java(18167) C(15235) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7219) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5344) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4580) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1979) 功能(1967) Web開發(1951) HtmlCss(1950) C++(1928) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1879) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Spring MVC官方檔案學習筆記(二)之DispatcherServlet

    **1.DispatcherServlet入門** (1) Spring MVC是以前端控制器模式(即圍繞著一個中央的Servelt, DispatcherServlet)進行設計的,這個DispatcherServlet為請求的處理提供了一個共用的演算法,即它都會將實際的請求處理作業委托給那些可配置 ......

    uj5u.com 2023-06-01 07:37:57 more
  • 別再滿屏找日志了!推薦一款 IDEA 日志管理插件,看日志輕松多了!

    ![](https://img2023.cnblogs.com/other/1218593/202305/1218593-20230531145646615-374710580.png) ## **1.簡介** Grep Console是一款方便開發者對idea控制臺輸出日志進行個性化管理的插件。 ......

    uj5u.com 2023-06-01 07:36:36 more
  • StampedLock:高并發場景下一種比讀寫鎖更快的鎖

    摘要:在讀多寫少的環境中,有沒有一種比ReadWriteLock更快的鎖呢?有,那就是JDK1.8中新增的StampedLock! 本文分享自華為云社區《【高并發】高并發場景下一種比讀寫鎖更快的鎖》,作者: 冰 河。 什么是StampedLock? ReadWriteLock鎖允許多個執行緒同時讀取共 ......

    uj5u.com 2023-06-01 07:31:08 more
  • BIO、NIO、AIO區別詳解

    ###BIO:同步阻塞 主執行緒發起io請求后,需要等待當前io操作完成,才能繼續執行。 ###NIO:同步非阻塞 引入selector、channel、等概念,當主執行緒發起io請求后,輪詢的查看系統是否準備好執行io操作,沒有準備好則主執行緒不會阻塞會繼續執行,準備好主執行緒會阻塞等待io操作完成。 # ......

    uj5u.com 2023-06-01 07:30:33 more
  • Java中泛型詳解,非常詳細

    # 前言 在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻并沒有詳細學習,**所以今天我們要花點時間給大家專門講解什么是泛型、泛型的作用、用法、特點等內容。** 有些粉絲朋友,在之前就一直很好奇,比如List中的 部分到底是什么?有啥用?為什么要加這個 ......

    uj5u.com 2023-05-31 10:10:59 more
  • Rust Web 全堆疊開發之 Web Service 中的錯誤處理

    # Rust Web 全堆疊開發之 Web Service 中的錯誤處理 ## Web Service 中的統一錯誤處理 ### Actix Web Service 自定義錯誤型別 -> 自定義錯誤轉為 HTTP Response - 資料庫 - 資料庫錯誤 - 串行化 - serde 錯誤 - I/ ......

    uj5u.com 2023-05-31 10:10:55 more
  • 驅動開發:內核決議PE結構匯出表

    在筆者的上一篇文章`《驅動開發:內核特征碼掃描PE代碼段》`中`LyShark`帶大家通過封裝好的`LySharkToolsUtilKernelBase`函式實作了動態獲取內核模塊基址,并通過`ntimage.h`頭檔案中提供的系列函式決議了指定內核模塊的`PE節表`引數,本章將繼續延申這個話題,實... ......

    uj5u.com 2023-05-31 10:10:44 more
  • keycloak~自定義登出介面

    keycloak提供了登出的介面,不過它是一個post方法,需要你根據client_id,client_secret及refresh_token進行登出操作的,有時不太靈活,所以我又自己封裝了一下,通過客戶端瀏覽器上存盤的session_id進行會話登出。 # kc提供的logout * api:{ ......

    uj5u.com 2023-05-31 10:10:35 more
  • Java中泛型詳解,非常詳細

    # 前言 在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻并沒有詳細學習,**所以今天我們要花點時間給大家專門講解什么是泛型、泛型的作用、用法、特點等內容。** 有些粉絲朋友,在之前就一直很好奇,比如List中的 部分到底是什么?有啥用?為什么要加這個 ......

    uj5u.com 2023-05-31 10:09:33 more
  • keycloak~自定義登出介面

    keycloak提供了登出的介面,不過它是一個post方法,需要你根據client_id,client_secret及refresh_token進行登出操作的,有時不太靈活,所以我又自己封裝了一下,通過客戶端瀏覽器上存盤的session_id進行會話登出。 # kc提供的logout * api:{ ......

    uj5u.com 2023-05-31 10:09:26 more