SpringBoot-02-SpringMVC


导入静态资源

直接找到WebMvcAutoConfiguration配置类(对应web开发)

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
    }
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    if (!registry.hasMappingForPattern("/webjars/**")) {
        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/")
                .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
        customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
                .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
                .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
}

发现项目路径resources/webjars/映射到了http://localhost:8080/webjars/

另外去https://www.webjars.org/得到jquery

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>

添加到pom.xml,左边会发现

(表示jQuery资源被放到了classpath:/META-INF/resources/)

http://localhost:8080/webjars/jquery/3.5.1/jquery.js

(除了classpath:/META-INF/resources/)其他存放静态资源的位置

 

http://localhost:8080/1.js


首页定制

还是在WebMvcAutoConfiguration配置类中

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
        FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
            new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
            this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
    return welcomePageHandlerMapping;
}

private Optional<Resource> getWelcomePage() {
    String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
    return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
}

private Resource getIndexHtml(String location) {
    return this.resourceLoader.getResource(location + "index.html");
}

private boolean isReadable(Resource resource) {
    try {
        return resource.exists() && (resource.getURL() != null);
    }
    catch (Exception ex) {
        return false;
    }
}

通常并不是将index.html放到到上述目录进行访问,而是放到templates下,通过controller进行跳转

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
/**
 * templates目录下的资源只能通过controller进行跳转而访问
 * 这种访问方式需要导入依赖
 */
@Controller
public class IndexController {

    @GetMapping("/index")
    public String index(){
        return "index";
    }
}

http://localhost:8080/

ico图标显示暂时没搞定(不同版本不一样https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-pathmatch)


Thymeleaf模板引擎

上文已经导入了依赖

这个东西就类似于freemarker(电商网站拿来生成静态页面用的)

它的自动配置类ThymeleafAutoConfiguration(叫这个名字跑不了了),对应的ThymeleafProperties

(视图解析)

在html的<html lang="en">标签中加入xmlns:th="http://www.thymeleaf.org"属性(导入命名空间/约束/头文件)

(用法:链接使用@  文本使用#)

@Controller
public class TestController {

    @RequestMapping("/test")
    public String test(Model model){
        //存入数据
        model.addAttribute("msg","Hello,Thymeleaf");
        //classpath:/templates/test.html
        return "test";
    }

    @RequestMapping("/test2")
    public String test2(Map<String,Object> map){
        //存入数据
        map.put("msg","<h1>Hello</h1>");
        map.put("users", Arrays.asList("xiaoming","xiaohong"));
        //classpath:/templates/test.html
        return "test";
    }
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--th:text就是将div中的内容设置为它指定的值-->
<div th:text="${msg}"></div>

<!--不转义-->
<div th:utext="${msg}"></div>
<!--遍历数据-->
<!--th:each每次遍历都会生成当前这个标签:官网#9-->
<h4 th:each="user :${users}" th:text="${user}"></h4>
<h4>
    <!--行内写法:官网#12-->
    <span th:each="user:${users}">[[${user}]]</span>
</h4>

</body>
</html>

MVC配置原理

官网学习https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

If you want to keep those Spring Boot MVC customizations and make more MVC customizations 
(interceptors, formatters, view controllers, and other features)
, you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

(通常自定义的配置类写在config包里边) 

//应为类型要求为WebMvcConfigurer,这是一个接口
// (一个人当过兵,我们说他是一个兵;一个人会下象棋,我们说他是一个棋手;接口丶)
//使用自定义类扩展视图解析器的功能
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Bean //放到bean中 进入容器
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    //我们写一个静态内部类,视图解析器就需要实现ViewResolver接口
    private static class MyViewResolver implements ViewResolver{
        @Override
        public View resolveViewName(String s, Locale locale) throws Exception {
            return null;
        }
    }
}

给 DispatcherServlet 类的 doDispatch 方法加断点,随便访问一个页面

发现自定义的视图解析器已经在容器中了(当然上面是为了说明原理,官方推荐的是如下做法实现视图跳转)

重写WebMvcConfigurer的方法  Alt+Insert

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 浏览器发送/test , 就会跳转到test页面;
        registry.addViewController("/test4").setViewName("test");
    }
}

http://localhost:8080/test4就轻松的跳转成功了

上面说自定义配置类不能加@EnableWebMvc这个注解,是因为这个注解会向容器中导入DelegatingWebMvcConfiguration这个类(WebMvcConfigurationSupport的子类),有了这个类之后,WebMvcAutoConfiguration就不满足@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)了,所以不能加丶

@EnableWebMvc全面接管SpringMVC的操作,据说是大厂写自己的starter才会用到,后面再继续了解

总之,看到了别人代码自定义的配置类(@Configuration修饰的XxxConfig),立马就要去看看他扩展了什么功能,因为这表示他动了springboot原有的东西丶


击石乃有火,不击元无烟!!
原文地址:https://www.cnblogs.com/rain2020/p/12757605.html