Spring基礎系列-Web開發

原創做品,能夠轉載,可是請標註出處地址:http://www.javashuo.com/article/p-thsqdhnv-ca.htmlhtml

SpringBoot基礎系列-web開發

概述

web開發就是集成Spring MVC進行開發,非REST開發。

整合Spring MVC

Spring MVC自動配置

當咱們在POM中添加spring-boot-starter-web以後,SpringBoot就會自動進行SpringMVC整合配置,這些配置內容包括:java

  • 自動建立ContentNegotiatingViewResolver和BeanNameViewResolver的實例Bean
  • 提供對持靜態資源,包括WebJar的支持
  • 自動建立Converter、GenericConverter和Formatter的實例Bean
  • 提供對HttpMessageConverters的支持
  • 自動建立MessageCodesResolver實例Bean
  • 提供對靜態歡迎頁面index.html的支持
  • 定製Favicon的支持
  • 自動使用ConfigurableWebBindingInitializer實例Bean

定製Spring MVC

定製方式一

保留默認的自動配置,而後在其基礎上新增一些配置:web

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    // 添加針對swagger的處理,避免swagger404
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
    }
    //...自定義實現WebMvcConfigurer中的若干默認方法
}

定製方式二

徹底控制Spring MVC,手動定製其各類功能:spring

@EnableWebMvc
@Configuration
public class WebMvcConfig {
    //...自定義實現WebMvcConfigurer中的若干默認方法
}

定製方式三

定製RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver實例:
經過聲明一個WebMvcRegistrationsAdapter實例來提供這些組件。json

HttpMessageConverters

即Http消息轉換器,主要用於轉換Http請求和響應,好比Objects會被自動轉換成爲JSON格式或者XML格式。編碼類型默認爲UTF-8。
能夠定製該轉換器,方式爲:跨域

@Configuration
public class MyConfiguration {
    // 定製HttpMessageConverters
    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<?> additional = ...
        HttpMessageConverter<?> another = ...
        return new HttpMessageConverters(additional, another);
    }
}

定製JSON序列化與反序列化

SpringBoot默認使用Jackson進行Json操做。
能夠定製序列化與反序列化操做,方式爲:瀏覽器

@JsonComponent
public class Example {
    public static class Serializer extends JsonSerializer<SomeObject> {
        // 定製json序列化邏輯...
    }
    public static class Deserializer extends JsonDeserializer<SomeObject> {
        // 定製json反序列化邏輯...
    }
}

或者spring-mvc

@JsonComponent
public static class Serializer extends JsonSerializer<SomeObject> {
    // 定製json序列化邏輯...
}

關於註解@JsonComponent

看看源碼:安全

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface JsonComponent {
    @AliasFor(annotation = Component.class)
    String value() default "";
}

能夠看到該註解是一個@Component,那麼他的做用就相似與@Component,主要用於註冊Bean。springboot

MessageCodesResolver

即消息編碼解析器,是Spring MVC內部用來生成錯誤編碼來表示錯誤信息的。

靜態內容

[待補充]

歡迎頁面

SpringBoot首先會查找index.html靜態歡迎頁面,若是找不到再查找index.ftl之類的模板歡迎頁面。

定製應用圖標

SpringBoot會在配置的靜態資源路徑和類路徑中(前後順序)查找favicon.ico圖標,將其用做應用圖標。

ConfigurableWebBindingInitializer

SpringMVC經過一個WebBindingInitializer來爲特定的請求提供一個WebDataBinder。若是自定義了ConfigurableWebBindingInitializer,那麼SpringBoot將自動配置使SpringMVC使用它。

模板引擎

SpringBoot提供對如下模板引擎的自動支持:

  • Freemarker
  • Groovy
  • Thymeleaf
  • Mustache

錯誤處理

默認狀況下,Spring Boot提供了一個/error映射,以合理的方式處理全部錯誤,並在servlet容器中註冊爲「全局」錯誤頁面。
即在SpringBoot內部提供了這麼一個控制器類BasicErrorController,接收/error請求,而後針對瀏覽器請求和客戶端請求兩種狀況做了映射,分別返回不一樣的內容。瀏覽器請求返回一個公共的錯誤頁面,而客戶端請求則返回一個ResponseEntity實例。

定製錯誤處理功能

方式一:定製錯誤頁面

定製錯誤頁面就是針對不一樣的code定義頁面
在resources目錄下的static目錄(或者templates目錄)下定義error目錄,在error目錄中定義401.html,404.html,500.html等錯誤頁面,一旦SpringBoot應用發生了40一、40四、500錯誤就會跳轉到自定義的錯誤頁面中,而對於未自定義編碼的錯誤還會跳轉到公共錯誤頁面
/static/error/404.html
/static/error/500.html
/templates/error/404.ftl
/templates/error/500.ftl

注意:必須定義到上面所說的目錄中,並且名稱必須爲:錯誤編碼.html格式,若是不按照以上規則,則定製不成功,其實若是想要自定義錯誤頁面地址和名稱也是能夠的,只不過須要多加一個步驟:
添加EmbeddedServletContainerCustomizer的Bean實例用於手動設置錯誤頁面的映射關係:
假如將500.html錯誤頁面建立到resources目錄下,也就是類路徑根目錄下,那麼就須要使用以下自定義的ErrorViewResolver來處理了:
/500.html
內容爲:

<p>根目錄的500錯誤文件</p>

MyErrorVivwResolver.java

@Component
public class MyErrorVivwResolver implements ErrorViewResolver,ApplicationContextAware {
   @Override
   public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
       Resource resource = this.applicationContext.getResource("classpath:/");
       try {
           resource = resource.createRelative(status.value() + ".html");
       } catch (IOException e) {
           e.printStackTrace();
       }
       ModelAndView modelAndView = new ModelAndView(new HtmlResourceView(resource), model);
       return modelAndView;
   }
   ApplicationContext applicationContext;
   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       this.applicationContext = applicationContext;
   }
   private static class HtmlResourceView implements View {
       private Resource resource;
       HtmlResourceView(Resource resource) {
           this.resource = resource;
       }
       @Override
       public String getContentType() {
           return MediaType.TEXT_HTML_VALUE;
       }
       @Override
       public void render(Map<String, ?> model, HttpServletRequest request,
                          HttpServletResponse response) throws Exception {
           response.setContentType(getContentType());
           FileCopyUtils.copy(this.resource.getInputStream(),
                   response.getOutputStream());
       }
   }
}

代碼中很多內容是抄自SpringBoot內置的DefaultErrorViewResolver。
頁面請求:

http://localhost:8080/error

頁面跳轉到500錯誤頁面,頁面顯示:

根目錄的500錯誤文件
方式二:無SpringMVC的錯誤頁面映射(通常不涉及)

在不使用SpringMVC的狀況下進行錯誤頁面映射,須要使用ErrorPageRegistrar(錯誤頁面註冊器)來直接註冊ErrorPages(錯誤頁面)。
這個註冊器直接與底層嵌入式servlet容器一塊兒工做,即便沒有Spring MVC的DispatcherServlet也能夠工做。

跨域請求

跨源資源共享(Cross-origin resource sharing, CORS)是由大多數瀏覽器實現的W3C規範,它容許您以靈活的方式指定哪一種跨域請求被受權,而不是使用一些不太安全、功能不太強大的方法,好比IFRAME或JSONP。
有兩種配置方式:

全局配置

全局配置針對的是應用的全部控制器接口

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    // 跨域請求全局配置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/book/**");
    }
    //...自定義實現WebMvcConfigurer中的若干默認方法
}

細粒度配置

細粒度指的是針對單個控制器中的方法,甚至是單個方法進行配置,使用@CrossOrigin註解

@RestController
@RequestMapping("/book")
@Api(description = "書籍接口")
@Log4j2
@CrossOrigin(maxAge = 3600)
public class BookApi {
    
    @Autowired
    private BookService bookService;
    
    @CrossOrigin("http://localhost:8081")
    @RequestMapping(value = "/getBook", method = RequestMethod.GET)
    @ApiOperation(value = "獲取一本書籍", notes = "根據ID獲取書籍", httpMethod = "GET")
    public ResponseEntity<Book> getBook(final int bookId){
        return bookService.getBook(bookId);
    }
}
相關文章
相關標籤/搜索