Spring Boot Web MVC 核心

2018-10-24  本文已影响0人  gringotts

理解Spring Web MVC架构

基础架构:Servlet


核心架构:前端控制器(Front Controller)

Spring Web MVC 架构

认识Spring Web MVC

Spring Framework时代的一般认识

实现Controller

@Controller
public class HelloWorldController {
    @RequestMapping("")
    public String index() {
        return "index";
    }
}

配置 Web MVC 组件

 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.imooc.web"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

部署DispatchServlet

<web-app>
    <servlet>
    <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app-context.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

使用可执行 Tomcat Maven 插件

 
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.1</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <!-- ServletContext path -->
                <path>/</path>
            </configuration>
        </execution>
    </executions>
</plugin>

Spring Framework时代的重新认识

Web MVC 核心组件

组件 Bean 类型 说明
HandlerMapping 映射请求(Request)到处理器(Handler)加上其关联的拦截器 (HandlerInterceptor)列表,其映射关系基于不同的 HandlerMapping 实现的一些 标准细节。其中两种主要 HandlerMapping 实现, RequestMappingHandlerMapping 支持标注 @RequestMapping 的方法, SimpleUrlHandlerMapping 维护精确的URI 路径与处理器的映射。
HandlerAdapter 帮助 DispatcherServlet 调用请求处理器(Handler),无需关注其中实际的调用 细节。比如,调用注解实现的 Controller 需要解析其关联的注解. HandlerAdapter 的主要目的是为了屏蔽与 DispatcherServlet 之间的诸多细节。
HandlerExceptionResolver 解析异常,可能策略是将异常处理映射到其他处理器(Handlers) 、或到某个 HTML 错误页面,或者其他。
ViewResolver 从处理器(Handler)返回字符类型的逻辑视图名称解析出实际的 View 对象,该对 象将渲染后的内容输出到HTTP 响应中。
LocaleResolver, LocaleContextResolver 从客户端解析出 Locale ,为其实现国际化视图。
MultipartResolver 解析多部分请求(如 Web 浏览器文件上传)的抽象实现

交互流程

MVC 注解驱动

@ComponentScan(basePackages = "com.imooc.web")
public class DispatchServletConfig {

}
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                System.out.println("拦截中....");
                return true;
            }
        });
    }

}
@Controller
public class HelloWorldController {
    @RequestMapping
    public String index(@RequestHeader("Accept-Language")String acceptLanguage,@CookieValue("JSESSIONID")String jsessionId, Model model){
//        model.addAttribute("acceptLanguage",acceptLanguage);
//        model.addAttribute("jsessionId",jsessionId);
//        model.addAttribute("message","hello,world");
        return "index";
    }
}
@ControllerAdvice(assignableTypes = HelloWorldController.class)
public class HelloWorldControllerAdvice {
    @ModelAttribute("acceptLanguage")
    public String acceptLanguage(@RequestHeader("Accept-Language")String acceptLanguage){
        return acceptLanguage;
    }

    @ModelAttribute("jsessionId")
    public String jsessionId(@CookieValue("JSESSIONID")String jsessionId){
        return jsessionId;
    }

    @ModelAttribute("message")
    public String message(){
        return "hello,world";
    }
    @ExceptionHandler(Throwable.class)
    public ResponseEntity<String> onException(Throwable throwable){
        return ResponseEntity.ok(throwable.getMessage());
    }
}

自动装配

Servlet SPI

Spring 适配

org.springframework.web.SpringServletContainerInitializer

Spring SPI

public class DefaultAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    //web.xml
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }
    //dispatchServlet
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{DispatchServletConfig.class};
    }

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

Spring Boot 时代简化Spring Web MVC

完全自动装配

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        ValidationAutoConfiguration.class })

理解自动装配顺序性

装配条件

Web类型判断(@ConditionalOnWebApplication
API判断(@ConditionalOnClass
Bean判断(@ConditionalOnMissingBean@ConditionalOnBean

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

外部化配置

Web MVC配置

org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties

spring.mvc.view.prefix = /WEB-INF/jsp/
spring.mvc.view.suffix = .jsp

Spring Boot JSP依赖

 <!-- Provided -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
上一篇 下一篇

猜你喜欢

热点阅读