Spring Boot官方文档学习——使用Spring Boot开发web应用程序

1. 使用Spring Boot开发web应用程序

        Spring Boot非常适合Web应用程序的开发。 您可以使用嵌入式Tomcat,Jetty或Undertow轻松创建自包含的HTTP服务器。 大多数Web应用程序将使用spring-boot-starter-web模块来快速启动和运行。

1.1 使用SpringBoot集成的Spring Web MVC框架

       Spring Web MVC框架(通常简称为“Spring MVC”)是一个丰富的“模型视图控制器”Web框架。 Spring MVC允许您创建特殊的@Controller或@RestController bean来处理传入的HTTP请求。 您的控制器中的方法使用@RequestMapping注释映射到HTTP。

       这里是一个典型的例子@RestController来提供JSON数据:

@RestController
@RequestMapping(value="/users")
public class MyRestController {

    @RequestMapping(value="/{user}", method=RequestMethod.GET)
    public User getUser(@PathVariable Long user) {
        // ...
    }

    @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
    List<Customer> getUserCustomers(@PathVariable Long user) {
        // ...
    }

    @RequestMapping(value="/{user}", method=RequestMethod.DELETE)
    public User deleteUser(@PathVariable Long user) {
        // ...
    }

}

1.1.1 Spring MVC自动配置

       Spring Boot为Spring MVC提供了自动配置,可以与大多数应用程序配合使用。自动配置在Spring的默认设置之上添加以下功能:

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver bean。
  • 支持静态资源,包括对WebJars的支持。
  • Converter,GenericConverter,Formatter beans的自动注册。
  • 支持HttpMessageConverters。
  • 自动注册MessageCodesResolver。
  • 静态index.html支持。
  • 自定义的Favicon支持。
  • 自动使用ConfigurableWebBindingInitializer。

        如果你想保持Spring Boot的MVC特性,并且你还想添加额外的MVC配置(拦截器,格式化器,视图控制器等),你可以添加你自己的@Configuration类型的WebMvcConfigurerAdapter。 如果您希望提供RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,则可以声明提供此类组件的WebMvcRegistrationsAdapter实例。

        如果你想完全控制Spring MVC,你可以添加你自己的用@EnableWebMvc注解的@Configuration。

1.1.2 HttpMessageConverters

        Spring MVC使用HttpMessageConverter接口来转换HTTP请求和响应。 默认包括拆箱即用的功能,例如对象可以自动转换为JSON(使用Jackson库)或XML(如果Jackson XML可以使用则使用Jackson XML扩展,否则使用JAXB)。 字符串默认使用UTF-8编码。如果您需要添加或自定义转换器,可以使用Spring Boot的HttpMessageConverters类。

import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<?> additional = ...
        HttpMessageConverter<?> another = ...
        return new HttpMessageConverters(additional, another);
    }

}

1.1.3 自定义JSON Serializers and Deserializers

        JSON序列化器和反序列化器

        如果您使用Jackson来序列化和反序列化JSON数据,则可能需要编写自己的JsonSerializer和JsonDeserializer类。 自定义序列化器通常通过模块向Jackson注册,但Spring Boot提供了一个替代的@JsonComponent注释,这使得更容易直接注册Spring Bean。

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

    public static class Serializer extends JsonSerializer<SomeObject> {
        // ...
    }

    public static class Deserializer extends JsonDeserializer<SomeObject> {
        // ...
    }

}
     ApplicationContext中的所有@JsonComponent bean将被自动注册到Jackson,并且由于@JsonComponent使用@Component进行元注释,所以通常的组件扫描规则适用。

        Spring Boot还提供了JsonObjectSerializer和JsonObjectDeserializer基类,在序列化对象时为标准Jackson版本提供了有用的替代方法。

        假设我们有个controller可以获取当前日期。我们可以发现:如果不加任何日期序列化工具,将会返回当前日期对应的毫秒数。

@RequestMapping("formatedate")

@JsonSerialize

public TestDate getFormatDate() {
    
	TestDate testDate = new TestDate();
    
	testDate.setCreatedate(new Date());
    
	return testDate;

}

如果我们自定义一个日期序列化工具,实现日期的格式化输出:

@JsonComponent


public class DateSerializer {



    public static class Serializer extends JsonSerializer<Date> {

        @Override

        public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException, JsonProcessingException {

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            jsonGenerator.writeString(simpleDateFormat.format(date));
}

    }



    public static class Deserializer extends JsonDeserializer<Date> {

        @Override

        public Date deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {

            String date = jsonParser.getText();

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            try {
return simpleDateFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}

            return new Date();
}

    }


}

观察输出,可以发现返回我们需要的日期格式:


同样反序列也也是一样的道理:

@RequestMapping(value = "str2date")

    public void getFormatDate(@RequestBody DateVO dateVO) {
System.out.println(dateVO);
}
@Data

public class DateVO {

    private Date date;

}

        入参我们用一个字符串时间:{"date":"2018-01-01 00:00:00"}我们自定的反序列化工具可以实现将字符串转换成Date对象DateVO(date=Mon Jan 01 00:00:00 CST 2018)。

1.1.4 MessageCodesResolver

        Spring MVC有一个策略,用于从绑定的errors产生用来渲染错误信息的错误码:MessageCodesResolver。如果设置spring.mvc.message-codes-resolver.format属性为PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(具体查看DefaultMessageCodesResolver.Format枚举值),Spring Boot会为你创建一个MessageCodesResolver。

1.1.5 Static Content(http://www.webjars.org/)

        默认情况下,Spring Boot将从类路径中的/ static(或/ public或/ resources或/ META-INF / resources)目录或从ServletContext的根目录中提供静态内容。 它使用Spring MVC中的ResourceHttpRequestHandler,因此可以通过添加自己的WebMvcConfigurerAdapter并重写addResourceHandlers方法来修改该行为。

        默认情况下,资源被映射到/ **,但是你可以通过spring.mvc.static-path-pattern来调整。 例如,将所有资源重定位到/ resources / **可以实现如下:

spring.mvc.static-path-pattern=/resources/**
        您还可以使用spring.resources.static-locations(使用目录位置列表替换默认值)自定义静态资源位置。 如果您这样做,默认的欢迎页面检测将切换到您的自定义位置。 因此,如果您的任何位置在启动时都有index.html,它将成为应用程序的主页。

        除了上面的“标准”静态资源位置之外,Webjars是一个特殊情况。 如果资源以Webjars格式打包,并且在/ webjars / **目录下,将会被当成jar包使用。

        如果您的应用程序将被打包为jar,请不要使用src/main/webapp目录。 虽然这个目录是一个通用的标准,但它只能用于war包,如果你要生成一个jar包,该目录会被大多数构建工具默默地忽略。

1.1.6 Custom Favicon

        Spring Boot会在配置的静态内容位置和类路径的根目录(按此顺序)中查找favicon.ico。 如果这样的文件存在,它会自动用作应用程序的图标。

1.1.7 ConfigurableWebBindingInitializer

    Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder。 如果您创建自己的ConfigurableWebBindingInitializer @Bean,Spring Boot将自动配置Spring MVC以使用它。

1.1.8 Template engines

        除了REST Web服务,您还可以使用Spring MVC为动态HTML内容提供服务。 Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。 许多其他模板引擎也提供了自己的Spring MVC集成。

        Spring Boot包含以下模板引擎的自动配置支持:

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache
        如果可能的话,JSP应该被避免,在嵌入的servlet容器中使用它们有几个已知的限制。
        当您使用默认配置的模板引擎之一时,您的模板将自动从src / main / resources / templates中选取。
        IntelliJ IDEA根据你不同的运行应用程序的方式排列类路径。 通过主要方法在IDE中运行应用程序将导致与使用Maven或Gradle或从其打包的jar运行应用程序时不同的顺序。 这可能会导致Spring Boot无法在类路径中找到模板。 如果您受到这个问题的影响,您可以在IDE中重新排序类路径,以便首先放置模块的类和资源。 或者,您可以配置模板前缀以搜索类路径中的每个模板目录:classpath *:/ templates /。
举个栗子:
        我现在想返回freemaker模本,需要做的准备工作如下:
  • 修改application.properties
## Freemarker 配置

## 文件配置路径

spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.cache=false

spring.freemarker.charset=UTF-8

spring.freemarker.check-template-location=true

spring.freemarker.content-type=text/html

spring.freemarker.expose-request-attributes=true

spring.freemarker.expose-session-attributes=true

spring.freemarker.request-context-attribute=request

spring.freemarker.suffix=.ftl
  • 新建controller返回视图名称
@RequestMapping("/welcome/{name}")

    public ModelAndView demo(@PathVariable String name) {
        
Map<String, Object> objectMap = new HashMap<>(1);

        objectMap.put("name", name);
return new ModelAndView("welcome");
    }
  • 新增/templates/welcome.ftl这个freemaker模版
<!DOCTYPE html>

<html>

	<head>
    
		<meta charset="UTF-8">
    
		<title>Insert title here</title>

	</head>

	<body>
    
		${name} 您好,欢迎您
<br/>

	</body>

</html>

        执行以下http://localhost:8080/users/welcome/张三,发现返回如下页面:


        更多关于freemaker的配置可以参考如下:

# FREEMARKER (FreeMarkerAutoConfiguration)
spring.freemarker.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name.
spring.freemarker.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name.
spring.freemarker.cache=false # Enable template caching.
spring.freemarker.charset=UTF-8 # Template encoding.
spring.freemarker.check-template-location=true # Check that the templates location exists.
spring.freemarker.content-type=text/html # Content-Type value.
spring.freemarker.enabled=true # Enable MVC view resolution for this technology.
spring.freemarker.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template.
spring.freemarker.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template.
spring.freemarker.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext".
spring.freemarker.prefer-file-system-access=true # Prefer file system access for template loading. File system access enables hot detection of template changes.
spring.freemarker.prefix= # Prefix that gets prepended to view names when building a URL.
spring.freemarker.request-context-attribute= # Name of the RequestContext attribute for all views.
spring.freemarker.settings.*= # Well-known FreeMarker keys which will be passed to FreeMarker's Configuration.
spring.freemarker.suffix=.ftl # Suffix that gets appended to view names when building a URL.
spring.freemarker.template-loader-path=classpath:/templates/ # Comma-separated list of template paths.
spring.freemarker.view-names= # White list of view names that can be resolved.

1.1.9 Error Handling

        Spring Boot默认提供了一个/error映射,以合理的方式处理所有的错误,并在servlet容器中被注册为一个“全局”错误页面。 对于机器客户端,它将产生一个JSON响应,包含错误的详细信息,HTTP状态和异常消息。 对于浏览器客户端,有一个'whitelabel'错误视图,它以HTML格式呈现相同的数据(自定义它只是添加一个解决'错误'的视图)。 要完全替换默认行为,可以实现ErrorController并注册该类型的bean定义,或者简单地添加一个ErrorAttributes类型的bean来使用现有的机制,但是替换内容。
        BasicErrorController可以用作自定义ErrorController的基类。 如果您想为新的内容类型添加处理程序(默认情况下专门处理text / html并提供其他所有内容的回退),这一点尤其有用。 要做到这一点,只需扩展BasicErrorController并添加一个带有@RequestMapping属性的公共方法,并创建一个新类型的bean。

        您还可以定义@ControllerAdvice来定制JSON文档以返回特定的控制器和/或异常类型.

@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler(YourException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
        HttpStatus status = getStatus(request);
        return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}

        在上面的例子中,如果由与FooController相同的包中定义的控制器抛出YourException,则将使用CustomErrorType POJO的json表示而不是ErrorAttributes表示形式。

        举个栗子:

@ControllerAdvice(basePackageClasses = MyRestController.class)

    public class CommonControllerAdvice extends ResponseEntityExceptionHandler {


        @ExceptionHandler(Exception.class)

        @ResponseBody

        ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {

            HttpStatus status = getStatus(request);

            return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
}



        private HttpStatus getStatus(HttpServletRequest request) {

            Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");

            if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}

            return HttpStatus.valueOf(statusCode);
}


    }

    @RequestMapping("exception")

    public void exceptionDemo() {
throw new RuntimeException("An uncaught Exception happened");
}

        可以看到控制台输出:

java.lang.RuntimeException: An uncaught Exception happened
	at com.example.springboot.controller.MyRestController.exceptionDemo(MyRestController.java:55) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.27.jar:8.5.27]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]

1.1.10 Custom error pages

        如果要为给定的状态代码显示自定义的HTML错误页面,请将文件添加到/ error文件夹。 错误页面可以是静态HTML(即添加在任何静态资源文件夹下),也可以使用模板构建。 该文件的名称应该是确切的状态码或一系列掩码。

        例如,要将404映射到静态HTML文件,您的文件夹结构如下所示:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

        要使用FreeMarker模板来映射所有的5xx错误,你会有这样的结构:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftl
             +- <other templates>

        对于更复杂的映射,您还可以添加实现ErrorViewResolver接口的bean。

public class MyErrorViewResolver implements ErrorViewResolver {

        @Override
        public ModelAndView resolveErrorView(HttpServletRequest request,
                                             HttpStatus status, Map<String, Object> model) {
            // Use the request or status to optionally return a ModelAndView
            return ...
        }

    }

        您还可以使用常规的Spring MVC功能,如@ExceptionHandler方法和@ControllerAdvice。 ErrorController将会接收任何未处理的异常。

git demo地址:https://github.com/PerseveranceForever/springmcv_demo.git

https://github.com/PerseveranceForever/springmcv_demo.git

猜你喜欢

转载自blog.csdn.net/shixuetanlang/article/details/79436103