springboot_web开发

3.19

目录

1.Springboot开发步骤

2.Springboot对静态资源的映射规则

3.模板引擎

引入Thymeleaf

Thymeleaf使用和语法

4.SpringMVC自动配置原理

5.修改Springboot的默认配置

6.全面接管SpringMvc

1.步骤:

1.创建springboot应用,选中需要的模块

2.springboot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来

3.编写业务代码

2.springboot对静态资源的映射规则:

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

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

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }
所有/webjars/**,都去classpath:/META-INF/resources/webjars/找资源webjars:以jar包的方式引入静态资源 https://www.webjars.org/
<!--引入jquery-webjar-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1</version>
        </dependency>
        <!--引入bootstrap-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.1.2</version>
        </dependency>

1)http://localhost:8084/webjars/jquery/3.3.1/jquery.js 能访问到引入的文档在访问的时候只需要写webjars下面资源的名称即可
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

2)/** 访问当前项目的任何资源

静态资源文件夹:

"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/""/":当前项目的根目录

为什么默认是这四个路径呢?可以看下面的源码。

/Users/mac/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.0.0.RELEASE/spring-boot-autoconfigure-2.0.0.RELEASE.jar!/org/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.class

 this.staticPathPattern = "/**";
 private static final String[] SERVLET_LOCATIONS = new String[]{"/"};

/Users/mac/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.0.0.RELEASE/spring-boot-autoconfigure-2.0.0.RELEASE.jar!/org/springframework/boot/autoconfigure/web/ResourceProperties.class

 private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

3)首页 静态资源下的所有index.html页面,被"/**"映射,localhost:8084/ 找index页面

4)配置喜欢的图标 也是在静态文件夹里找

源码:

  @Bean
            public SimpleUrlHandlerMapping faviconHandlerMapping() {
                SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
                mapping.setOrder(-2147483647);
                mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", this.faviconRequestHandler()));
                return mapping;
            }

修改成功!

5)修改默认静态资源路径 application.properties

#多个路径可以用,隔离开路径
spring.resources.static-locations=classpath:/hello/,classpath:/public/
3.模板引擎JSP、Velocity、Freemarker、Thymeleafspringboot推荐的Thymeleaf:语法更简单,功能更强大1.引入thymeleaf2.0.0版本springboot默认导入的是3.0.9版本的thymeleaf
  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

2.thymeleaf使用和语法

@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";

把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染

thymeleaf语法官方文档:

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.pdf

使用:

1)导入thymeleaf的名称空间

<html lang="en" xmlns:th="http://www.thymeleaf.org">

2)表达式

--------------------------

success.xml

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--th:text将div里面的文本内容替换

 th:任意HTML属性,来替换原生属性的值
-->
   <div th:text="${hello}"></div>
<div th:utext="${hello}"></div>
<!--th:each每次遍历都会生成当前这个标签
3个h4-->
<h4 th:text="${user}" th:each="user:${users}"></h4>
<h4>
    <!--3个span-->
    <span th:each="user:${users}">[[${user}]]</span>
</h4>
</body>
</html>

helloController.java

package com.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Map;
/*
@[email protected][email protected]
 */
@Controller
public class helloContronller {
   @RequestMapping("/success")
    public String success(Map<String,Object>map){
        map.put("hello","<h1>123888910<h1>");
        map.put("users", Arrays.asList("zhangsan","lalala"));
       return "success";
   }
}

实验结果:

4.springMVC自动配置原理

官方文档:

https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

1.

Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

自动配置视图了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染)

ContentNegotiatingViewResolver 组合所有的视图解析器

源码:

WebMvcAutoConfiguration.class

        @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;
        }
可以看到ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();进入ContentNegotiatingViewResolver类 找到其中的resolveViewName方法,看如何解析视图。
  @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
        Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
        List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
              if (requestedMediaTypes != null) {
            List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
            View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
            if (bestView != null) {
                return bestView;
··· ···

视图通过getCandidateViews方法获取,进入该方法发现该方法获取viewResolvers视图解析器并遍历
 private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception {
        List<View> candidateViews = new ArrayList();
        if (this.viewResolvers != null) {
            Assert.state(this.contentNegotiationManager != null, "No ContentNegotiationManager set");
            Iterator var5 = this.viewResolvers.iterator();

            while(var5.hasNext()) {
                ViewResolver viewResolver = (ViewResolver)var5.next();
                View view = viewResolver.resolveViewName(viewName, locale);
                if (view != null) {
                    candidateViews.add(view);
                }
··· ···

那么视图解析器viewResolvers是怎么得到的呢?通过BeanFactory工具从容器中获取所有视图解析器。

protected void initServletContext(ServletContext servletContext) {
        Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
        ViewResolver viewResolver;
        if (this.viewResolvers == null) {
            this.viewResolvers = new ArrayList(matchingBeans.size());
            Iterator var3 = matchingBeans.iterator();
··· ···

也就是说:

BeanFactory工具从容器中获取所有视图解析器viewResolvers

->getCandidateViews方法获取viewResolvers并遍历,返回值是List<View>列表

->在ContentNegotiatingViewResolver类中,resolveViewName方法使用getCandidateViews方法解析视图,返回值是View

->在ContentNegotiatingViewResolver类中,创建该类对象

所以,ContentNegotiatingViewResolver 组合了所有的视图解析器。

如何定制视图解析器:可以给容器中添加一个视图解析器,自动将其组合进来。通过测试验证正确性:

DemoApplication.java

package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import java.util.Locale;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    //将自己的视图解析器增加到容器中
    @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.class的doDispatch方法处打上断点,debug

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
 

可以看到在容器中已经将自定义ViewResolver的组件添加进来了(蓝色行)

Support for serving static resources, including support for WebJars (covered later in this document)).静态资源文件夹路径webjars

Automatic registration of Converter, GenericConverter, and Formatter beans.

Converter: 转化器 类型转换

GenericConverter

Formatter:格式化器

自己也可以添加格式化器转换器,只需放在容器中

Support for HttpMessageConverters (covered later in this document).

HttpMessageConverters:springboot用来转换Http请求和响应的,从容器中确定,获取所有的HttpMessageConverter 可以自己配置,添加到容器

Automatic registration of MessageCodesResolver (covered later in this document). 定义错误代码生成规则 可以自己配置,添加到容器

Static index.html support.  静态资源首页

Custom Favicon support (covered later in this document).  图标设置 可以自己配置,添加到容器

Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document). 初始化ConfigurableWebBinder把请求数据绑定到JavaBean中  可以自己配置,添加到容器

更多容器中的组件具体可以看:org.springframework.boot.autoconfigure.web.servlet 里的xxxConfiguration类:web的所有自动配置场景。

5.修改springboot的默认配置

模式:

" ‘‘ ‘‘

If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.‘‘ ‘‘ ‘‘

1)springboot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component),如果有就用户配置的,如果没有才自动配置。如果有些组件可以有多个(ViewResolver)将用户配置和默认配置组合起来。

2)

扩展springmvc

springmvc.xml

<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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<mvc:view-controller path="/hello" view-name="success"/>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean></bean>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

原来在springmvc中可以如上配置(拦截hello请求),那么在springboot中不写xml配置文件怎么实现呢?

编写一个配置类(@Configuration)继承父类重写方法,不能标注@EnableWebMvc注解(springmvc的自动配置和我们的扩展配置都会生效,如果加上@EnableWebMvc则springmvc的自动配置全部失效-具体原因参见源码)。

package com.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class MyMvcConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {
        //super.addViewControllers(registry);
        //浏览器发送/s请求,也来到success页面
        registry.addViewController("/s").setViewName("success");
    }
}

6.全面接管SpringMvc(开发中不推荐)

springboot对springmvc的自动配置不需要了,所有都是自己配置。所有的springmvc的自动配置都失效了。

需要在配置类中添加@EnableWebMvc注解。

@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {

原理:

进入@EnableWebMvc

@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {

进入DelegatingWebMvcConfiguration.class

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

在自动配置类WebMvcConfiguration.class可以看到:

@Configuration
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
//容器中缺少 WebMvcConfigurationSupport类型的bean时,自动配置类才会生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
    public static final String DEFAULT_PREFIX = "";
    public static final String DEFAULT_SUFFIX = "";

也就是说:@EnableWebMvc将DelegatingWebMvcConfiguration类中对应的组件都导入到容器中,而这个类是继承WebMvcConfigurationSupport类的,所以将父类中的组件也会导入容器。在自动配置类中可以看到,只有容器中没有WebMvcConfigurationSupport类中组件,这个自动配置类才会生效。而此时容器中已经有了WebMvcConfigurationSupport类中组件,所以自动配置类不会再生效了。

原文地址:https://www.cnblogs.com/zuiaimiusi/p/12523811.html

时间: 2024-08-09 22:24:37

springboot_web开发的相关文章

eclipse birt报表开发入门

在开发中,报表或多或少会涉及到,有些报表可能比较简单,而有些报表可能很复杂.无论如何,这些报表功能的开发都是可以通过一些公共的组件来实现的,比如我现在所在的这家公司,如果想要制作报表,只需要配置下报表配置下就可以了(这个报表是通过特定实现的报表语言实现了,支持内部自定义的语言,最终将这些相应的数据保存到数据库中,对报表中的一些事物进行了抽象,比如:报表模型, 查询参数.).如果要自己手动的一步一步的编写报表,那么相对会比较麻烦,如果能提供一个框架,只需要进行一些配置就可以完成自定义报表,那岂不很

微信公众号可通过现金红包接口发放微信支付现金红包(附开发教程)

农历新年将至,支付宝红包打了一仗,微信在朋友圈屏蔽了它的分享,但单防守还不行,进攻才是最好的防守.昨日,微信支付现金红包接口正式开放,只需开通微信支付,即可接入现金红包.微信公众号也可以发放现金红包了! 通过现金红包接口,公众号开发者可以策划相关运营活动,向用户发放微信支付现金红包,更好的达到品牌推广及回馈用户的效果. 1.商户调用接口时,通过指定发送对象以及发送金额的方式发放红包,这样的方式,允许商户灵活的应用于各种各样丰富的活动场景 2.领取到红包后,用户的资金直接进入微信零钱,避免繁复的领

基于jquery开发的UI框架整理分析

根据调查得知,现在市场中的UI框架差不多40个左右,不知大家都习惯性的用哪个框架,现在市场中有几款UI框架稍微的成熟一些,也是大家比较喜欢的一种UI框架,那应该是jQuery,有部分UI框架都是根据jQuery研发出来的产品,现在也很常见了. 国产jQuery UI框架 (jUI) DWZ DWZ富客户端框架(jQuery RIA framework), 是中国人自己开发的基于jQuery实现的Ajax RIA开源框架.设计目标是简单实用,快速开发,降低ajax开发成本. jQuery 部件布局

【Windows10&nbsp;IoT开发系列】配置篇

原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry Pi.MinnowBoard和Galileo平台上的核心版.本文重点针对Raspberry Pi平台的Windwos10 IoT配置做介绍. Windows 10 IoT Editions ​一:设置你的电脑. 注:​开发Windows10 IoT的电脑需要Visual Studio 2015.

【Windows10&nbsp;IoT开发系列】PowerShell的相关配置

原文:[Windows10 IoT开发系列]PowerShell的相关配置 可使用 Windows PowerShell 远程配置和管理任何 Windows 10 IoT 核心版设备.PowerShell 是基于任务的命令行 Shell 和脚本语言,专为进行系统管理而设计. 1.​启动 PowerShell (PS) 会话 注:若要使用装有Windows10 IoT Core设备启动PS会话,首先需要在主机电脑与设备之间创建信任关系. ​启动 Windows IoT 核心版设备后,与该设备相连的

【Windows10&nbsp;IoT开发系列】API&nbsp;移植工具

原文:[Windows10 IoT开发系列]API 移植工具 Windows 10 IoT Core 中是否提供你的当前 Win32 应用程序或库所依赖的 API? 如果不提供,是否存在可使用的等效 API? 此工具可以为你回答这些问题,并协助你将你的当前 Win32 应用程序和库迁移到 Windows IoT Core. Windows 10 IoT 核心版 API 移植工具可在 ms-iot/iot-utilities github 存储库中找到.下载存储库 zip 并将 IoTAPIPor

【Windows10&nbsp;IoT开发系列】“Hello,World!”指导

原文:[Windows10 IoT开发系列]"Hello,World!"指导 本文主要是介绍使用C#来开发一个可以运行在Raspberry Pi2上的一个基本项目. ​1.在启动Visual Studio 2015后,选择"文件"→"新建项目". ​在打开的"新建项目"对话框中,选择"通用". ​选择第一个项目"空白应用(通用Windows)" 新建项目 ​注:如果这是你创建的第一个项

【Windows10&nbsp;IoT开发系列】开发人员模式设置

原文:[Windows10 IoT开发系列]开发人员模式设置  声明:本文转自微软Windows 开发人员中心(https://msdn.microsoft.com/library/windows/apps/xaml/dn706236.aspx),在此基础上进行删减和修改. ​对于要用于开发.安装或测试应用的设备,不再需要开发人员许可证.你只需从设备的设置中为这些任务启用设备一次.(仅限于运行Windows 10系统的设备) 使用开发人员功能 ​使用 Microsoft Visual Stud

二维码扫码积分系统定制开发

微信积分系统 二维码扫码积分系统定制开发找丽姐[158.1816.6626/电微]二维码营销模式系统定制开发 微信扫二维码营销系统开发 扫码领积分系统开发 一.如何实现扫二维码领红包功能? 1.使用扫描二维码领取红包对活动进行设置,包括红包数量.红包金额.促销地区.中奖概率等. 2.将生成的二维码赋到商品上面并赋涂层,一方面可以起到保证二维码的一次性,另一方面也可以引起消费者的好奇心. 3.通过手机微信打开扫一扫,扫码商品二维码关注公众号并领取红包,如果参与分享还可以获得抽奖的机会. 二.微信扫