SpringBoot 基础系列 - web 开发
概述
Web 开发就是集成 Spring MVC 进行开发, 非 REST 开发.
整合 Spring MVC
Spring MVC 自动配置
当我们在 POM 中添加 spring-boot-starter-Web 之后, SpringBoot 就会自动进行 SpringMVC 整合配置, 这些配置内容包括:
自动创建 ContentNegotiatingViewResolver 和 BeanNameViewResolver 的实例 Bean
提供对持静态资源, 包括 WebJar 的支持
自动创建 Converter,GenericConverter 和 Formatter 的实例 Bean
提供对 HttpMessageConverters 的支持
自动创建 MessageCodesResolver 实例 Bean
提供对静态欢迎页面 index.html 的支持
定制 Favicon 的支持
自动使用 ConfigurableWebBindingInitializer 实例 Bean
定制 Spring MVC
定制方式一
保留默认的自动配置, 然后在其基础上新增一些配置:
- @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, 手动定制其各种功能:
- @EnableWebMvc
- @Configuration
- public class WebMvcConfig {
- //... 自定义实现 WebMvcConfigurer 中的若干默认方法
- }
定制方式三
定制 RequestMappingHandlerMapping,RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 实例:
通过声明一个 WebMvcRegistrationsAdapter 实例来提供这些组件.
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 反序列化逻辑...
- }
- }
或者
- @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.
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 应用发生了 401,404,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);
- }
- }
来源: https://www.cnblogs.com/V1haoge/p/9996902.html