springboot web开发准备

本文介绍 Spring Boot 中 web 应用的开发方法,包括静态资源处理、前端页面配置及 Thymeleaf 模板引擎的使用。同时,探讨如何自定义配置类以增强项目的灵活性。

springboot项目文件夹下我们找不到 web-app文件夹

我们该如何开发web-application

静态资源

前端页面

持久处理

静态资源

1、存放位置

在resources 目录下 为我们准备了 statictemplates

static 用来存放静态资源

templates 用来存放模板文件

  • templates
    n. 模板;范本(template的复数);属性单元
1.2、源码分析

找到springmvc的自动装配类 WebMvcAutoConfiguration.class

protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    super.addResourceHandlers(registry);
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    } else {
        ServletContext servletContext = this.getServletContext();
        this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
        this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
            registration.addResourceLocations(this.resourceProperties.getStaticLocations());
            if (servletContext != null) {
                registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});
            }

        });
    }
}
  • if (!this.resourceProperties.isAddMappings()) {
          logger.debug("Default resource handling disabled");
      }
    
    • 我们直译 如果属性配置类被加入到映射路径 默认资源处理关闭
    • 当我们在配置文件中配置了自己的 静态资源路径那么默认资源路劲就会失效
  • this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
    
    • 加入了一个资源处理器 路径为 /webjars/**
      • **会映射到对应资源的webjars/下的路径

WebJars是将客户端(浏览器)资源(JavaScript,Css等)打成jar包文件,以对资源进行统一依赖管理。

我们访问官网为项目添加webjars的jquery 依赖

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

在项目的扩展库中可以发现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G8AFhYH6-1620568482718)(C:\Users\Xingcl\AppData\Roaming\Typora\typora-user-images\image-20210509125945082.png)]

  • 如果我们要访问用webjars 管理的静态资源

    • 可以使用 项目地址:项目端口/webjars/资源名/资源版本号/具体资源名
    • localhost:8080/webjars/jquery/3.6.0/jquerys.js
    • 大概就是 webjars/会映射到所有我们导入的webjars 静态资源的webjars路径下
  • this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                if (servletContext != null) {
                    registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});
                }
    
            });
    
    • 这里使用lamda 表达式还加入了一个 路径

      • 通过源码深入我们发现了这样一个路径 this.staticPathPattern = "/**";

      • 按照webjars 我们可以理解静态资源的路径是由方法 addResourceLocations第二个字符串参数和第三个字符串参数拼接的

      • 在第二个参数 我们发现了

        • new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/","classpath:/public/"}
          
  • 那么/**应该就是映射到这四个路径下了 我们可以使用(就像直接映射到对应资源的webjars 目录)

    • 主机名:端口号/资源名 需要保证资源存在在以上四个路径中
    • localhost:8080/资源名
  • 优先级

classpath:/resources/>classpath:/static/>classpath:/public/

网站主页

1、源码分析
private Resource getWelcomePage() {
    String[] var1 = this.resourceProperties.getStaticLocations();
    int var2 = var1.length;

    for(int var3 = 0; var3 < var2; ++var3) {
        String location = var1[var3];
        Resource indexHtml = this.getIndexHtml(location);
        if (indexHtml != null) {
            return indexHtml;
        }
    }

    ServletContext servletContext = this.getServletContext();
    if (servletContext != null) {
        return this.getIndexHtml((Resource)(new ServletContextResource(servletContext, "/")));
    } else {
        return null;
    }
}

private Resource getIndexHtml(String location) {
    return this.getIndexHtml(this.resourceLoader.getResource(location));
}

private Resource getIndexHtml(Resource location) {
    try {
        Resource resource = location.createRelative("index.html");
        if (resource.exists() && resource.getURL() != null) {
            return resource;
        }
    } catch (Exception var3) {
    }

    return null;
}
  • String[] var1 = this.resourceProperties.getStaticLocations();
    
    • resourceLoader还是从我们的静态资源路径下去寻找首页

      • this.getIndexHtml(location);(String)
        

        会走这个方法

        • 到这

          getIndexHtml(Resource location) 
          
    • 如果找不到会判断servlet上下文是否存在 如果存在会从上下文中寻找

 return this.getIndexHtml((Resource)(new ServletContextResource(servletContext, "/")));

应该是用controller访问首页

ThymeLeaf

ThymeLeaf is a modern server-side Java template engine for both web and standalone environments.

它是一个流行的适合web和独立环境的服务器端java模板引擎

  • 一个模板引擎

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sivyy9H1-1620568482720)(https://th.bing.com/th/id/R077a2428811b7e3d3674a80f87e827f4?rik=PUOwjN0my0S8YQ&riu=http%3a%2f%2fupload-images.jianshu.io%2fupload_images%2f8707272-8346cf5c4b91b284.png&ehk=2HTJTJjlnO5HubAAna0DDWE78diyB0tXUENMwvmrpEU%3d&risl=&pid=ImgRaw)]

  • 将我们的数据装载到前端页面 (jsp被springboot摒弃了 )然后生成最后展示给用户的效果页面
1、依赖导入
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
   <version>2.4.5</version>
</dependency>
  • 我们导入启动器
2、添加约束
 xmlns:th="http://www.thymeleaf.org"

在前端页面使用 ThymeLeaf 的标签去取得数据

标签作用示例
th:id替换id<input th:id="${user.id}"/>
th:text文本替换<p text:="${user.name}">bigsai</p>
th:utext支持html的文本替换<p utext:="${htmlcontent}">content</p>
th:object替换对象<div th:object="${user}"></div>
th:value替换值<input th:value="${user.name}" >
th:each迭代<tr th:each="student:${user}" >
th:href替换超链接<a th:href="@{index.html}">超链接</a>
th:src替换资源<script type="text/javascript" th:src="@{index.js}"></script>
  • <p th:text="${test}"></p>
    

还是类似springmvc 拼接前后缀

ThymeLeaf的标签能够绑定所有的html标签

SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(this.applicationContext);
resolver.setPrefix(this.properties.getPrefix());
resolver.setSuffix(this.properties.getSuffix());
resolver.setTemplateMode(this.properties.getMode());
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
  • 拼接前缀 classpath:/templates/ 所以为了能够访问我们应该把页面文件放在 templates 路径下
  • 后缀 .html
3、定义接口
@RequestMapping("/test")
public ModelAndView thymeleaf(ModelAndView model)
{
    model.addObject("test","hello thymeleaf");
    model.setViewName("test");
    return model;
}
4、访问结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t8kGbLur-1620568482723)(C:\Users\Xingcl\AppData\Roaming\Typora\typora-user-images\image-20210509170008884.png)]

5、thymeleaf 的特点
5.1、动静分离
  • 使用html 最为模板 但是有自己独有的标签 没有破坏 html 结构

  • 无网络 不访问后端也能打开前端页面

    • 我们打开jsp页面时如果 嵌套了一些引擎语句 那么我们的前端页面如果没有网络访问去后端是会 抛出错误码的 而且后端数据出错了也会抛出错误码
    • **这个特点超级重要 ** 那么前端在测试一些东西时可以完全独立了
5.2、开箱即用
  • Thymeleaf提供标准和Spring标准两种方言 直接套用模板实现JSTL、 OGNL表达式效果
6、语法
自定义和应用配置

在我们使用springboot开发web项目时 其实springboot 把 诸如 dispatcherServlet (前端控制器) viewResolver (视图解析器) 等之类的都作为组件装配到Ioc 容器中了,但是这并不意味着我们不能掌控这个过程了,如果对自动装配的原理了解,我们可以接管或者拓展 springmvc的组件。

2.1.1 发布的spring boot中文文档有这样一段话

如果您想保留 Spring Boot MVC 功能,并且想要添加其他MVC configuration(拦截器,格式化程序,视图控制器和其他功能)

可以添加自己的@Configuration类,类型为WebMvcConfigurer,但是 没有 @EnableWebMvc。如果希望提供RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMvcRegistrationsAdapter实例以提供此类件。

如果要完全控制 Spring MVC,则可以添加自己的@Configuration并以@EnableWebMvcComments。

  • 可以添加自己的配置类

  • @Configuration

    • 自定义配置类需要该注解标注未配置类
  • @EnableWebMvc

    • 使用该注解可以摒弃默认被注册的组件 使用自定义的组件接管
    • 如果拓展请不要加上该注解
  • 自定义的属性配置类一定是 WebMvcConfigurer (继承或实现)

2.4.5 的英文文档案中同样有这样一句

The easiest way to take complete control over MVC configuration is to provide your own @Configuration with the @EnableWebMvc annotation. Doing so leaves all MVC configuration in your hands.

接管springmvc 最简单的方法是使用 @Configuration 配合 @EnableWebMvc 注解提供你自己的

1、 自定义配置类

尝试自定义一个视图解析器

@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix(this.mvcProperties.getView().getPrefix());
    resolver.setSuffix(this.mvcProperties.getView().getSuffix());
    return resolver;
}

@Bean
@ConditionalOnBean({View.class})
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
    BeanNameViewResolver resolver = new BeanNameViewResolver();
    resolver.setOrder(2147483637);
    return resolver;
}

@Bean
@ConditionalOnBean({ViewResolver.class})
@ConditionalOnMissingBean(
    name = {"viewResolver"},
    value = {ContentNegotiatingViewResolver.class}
)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
    resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
    resolver.setOrder(-2147483648);
    return resolver;
}

三个官方的视图解析器在这里装配

  • WebMvcAutoConfiguration
    
  • @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
    
2、自定义ViewRsolver
//实现视图解析器接口成为一个视图解析器
public class MyViewResolver implements ViewResolver {

    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {
        return null;
    }
}
3、扩展配置类
@Configuration
//标记未配置类
//@EnableWebMvc
//接管springmvc配置
public class MyWebConfig implements WebMvcConfigurer {

    @Bean
    public ViewResolver selfViewResolver() {
        return new MyViewResolver();
    }
    //注册到Ioc容器中去

}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8QDzJkRN-1620568482724)(C:\Users\Xingcl\AppData\Roaming\Typora\typora-user-images\image-20210509214203350.png)]

  • 我们在dispatcherServlet中ViewResolver中找到了我们自定义的视图解析器

如果我们要接管需要定义很多属性 配合@EnableWebMvc

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

它导入了 DelegatingWebMvcConfiguration.class

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport

该类又继承了 WebMvcConfigurationSupport

会触发

@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})

专配该类需要满足没有WebMvcConfigurationSupport.class

所以当使用 @EnableWebMvc默认自动装配 类会失效

自定义的配置类会接管

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值