使用spring Initializer快速创建spring Boot项目

一.springBoot简介

1.优点:

​ 1.1 快速创建独立运行的spring项目以及主流框架集成

​ 1.2 使用嵌入式的Servlet容器,应用无需打成WAR包、

​ 1.3 starters 自动依赖和版本控制

​ 1.4 大量的自动配置,简化开发,也可修改默认值

​ 1.5 准生产环境的运行时应用监控

​ 1.6 与云计算的天然集成

简化spring应用开发的一个框架

二.微服务

微服务:架构风格

一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;

每一个功能元素最终都是一个可独立替换和独立升级的软件单元。

三.springboot HelloWorld

一个功能:

浏览器发送hello请求,服务器接收请求并处理。

1.创建一个maven工程

2导入springBoot相关依赖

  <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>

    <!-- Override inherited settings -->
    <description/>
    <developers>
        <developer/>
    </developers>
    <licenses>
        <license/>
    </licenses>
    <scm>
        <url/>
    </scm>
    <url/>

    <!-- Add typical dependencies for a web application -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

  

3.编写一个主程序;启动spring Boot应用

package com.tree;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 利用@SpringBootApplication注解告诉springBoot 这是一个spring boot 应用
 */
@SpringBootApplication
public class HelloWordMainApplication {
    public static void main(String[] args) {
        //启动spring boot 应用
        SpringApplication.run(HelloWordMainApplication.class,args);
    }

}

4. 编写service 、controller

package com.tree;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 利用@SpringBootApplication注解告诉springBoot 这是一个spring boot 应用
 */
@SpringBootApplication
public class HelloWordMainApplication {
    public static void main(String[] args) {
        //启动spring boot 应用
        SpringApplication.run(HelloWordMainApplication.class,args);
    }

}

四. 运行主程序测试

五.简化部署

  <!-- 这个插件,可以将应用打包成一个可执行的jar包 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

将这个应用打成jar包,直接使用java -jar xxx.jar的命令进行使用

六.Hello World探索

6.1 POM文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>
这是一个父项目,他的父项目是:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>
这个父项目是真正管理spring boot应用里面的所有依赖版本

spring boot版本仲裁中心;

导入依赖默认不需要写版本;(没有在dependencies里面管理的依赖,需要声明版本号)

6.2 启动器:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

spring-boot-starter-web;

spring-boot-starter: spring boot场景启动器;帮我们导入web模块正常运行索依赖的组件;

spring boot将所有的功能场景都抽取出来,做成一个个starters(启动器),只需要在项目中引入这些相关场景的所有依赖都会导入进来。要用某一个功能就导入什么场景的启动器。

6.3 主程序类,入口类;

/**
 * 利用@SpringBootApplication注解告诉springBoot 这是一个spring boot 应用
 */
@SpringBootApplication
public class HelloWordMainApplication {
    public static void main(String[] args) {
        //启动spring boot 应用
        SpringApplication.run(HelloWordMainApplication.class,args);
    }

}

@SpringBootApplication: Spring boot应用标注在某个类上,说明这个类是spring boot的主配置类。spring boot就应该运行这个类的main方法来启动spring boot应用

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

@SpringBootConfiguration : spring boot的配置类;

​ 这个注解标注在某个类上, 表示这个类是spring boot的配置类

​ @Configuration : 配置类上来标注这个额注解;

​ 配置类 == 配置文件;配置类也是容器中的一个组件;@Component

@EnableAutoConfiguration ;开启自动配置功能;

​ 以前我们需要配置的东西,springboot帮我们自动配置; @EnableAutoConfiguration告诉springboot 开启自动配置功能;这样自动配置才能生效。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

@AutoConfigurationPackage: 自动配置包

​ @Import(AutoConfigurationPackages.Registrar.class)

​ spring的底层注解@Import ,给容器中导入一个组件;导入的组件由 @Import(AutoConfigurationPackages.Registrar.class);

将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到spring容器;

@Import(AutoConfigurationImportSelector.class)

​ 给容器中导入组件;

​ AutoConfigurationImportSelector : 导入哪些组件的选择器;

​ 将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;

​ 会给容器中导入自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景导入需要的所有组件,并配置好这些组件;

有了自动配置类,免去了手动配置写配置注入功能组件。

​ spring-boot-autoconfigure.jar 帮我们自动配置了J2ee所有解决方案

七. 使用spring initializer快速创建spring boot项目

默认生成的sping boot项目;

  • 主程序已经生成好了,只需要添加自己的逻辑即可
  • resources文件夹中目录结构
    1. static:保存素有的静态资源;js css images;
    2. templates;保存所有的模板页面;springboot 默认jar包使用嵌入式的tomcat,默认不支持jsp页面,可以使用模板引擎,freemarker/ thymeleaf;
    3. application.properties:springboot配置文件,可以修改一些默认配置。

八. spring boot配置文件

spring boot 使用一个全局配置文件,配置文件名是固定的;

  1. application.properties

  2. application.yml

    配置文件的作用:修改springboot自动配置的默认值;

YAML(YAML Ain’t Markup language)

​ 以数据为中心的标记语言

示例:

server:
  port: 8081

8.1 YAML语法:

  1. 基本语法:

    k:(空格)v : 表示一对键值对(空格必须有);

    以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一 个层级的;

server:
	port: 8081
	path: /hello

属性和值大小写敏感;

  1. 值的写法:

    字面量:普通的值(数字,字符串,布尔)

    k: v:字面直接来写;

    字符串默认不用加上单引号或者双引号;

    对象、map(属性和值):

    对象还是k;v的方式

    friends:
    	name:zhangsan
    	age:20
    
    

    行内写法:

    friends:{name: zhangsan,age: 20}
    
    

    数组(List/set):

    用 - 值表示数组中的一个元素

    pets:
    	- cat
    	- dog
    	- pig
    
    

    行内写法:

    pets: [cat,dog,pig]
    
    

3. 配置文件值注入:

person:
  lastName: zhangsan
  age: 18
  boos: false
  birth: 2020/12/12
  maps: {k1: v1,k2: v2}
  lists:
    - lisi
    - zhaoliu
  dog:
    name: 小狗
    age: 6

javaBean

/**
 * 将配置文件中的属性值映射到这个组件中
 * @ConfigurationProperties 告诉springboot 将本类中的所有属性和配置文件中相关的配置进行绑定
 * prefix = "person"  配置文件中哪个属性进行一一配置
 * 只用实体类是一个组件时,才能使用属性配置
 */
@Component
@ConfigurationProperties(prefix = "person")  //默认从全局配置文件中进行获取值
public class Person {
    private String lastName;
    private Integer age;
    private Boolean boos;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;

需要导入配置文件处理器,编写配置文件就会有提示:

<!--		配置文件处理器 配置文件进行绑定就会有提示-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-	 processor</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

利用properties文件进行属性注入:

person.age=12
person.birth=2020/7/7
person.boos=true
person.last-name=张三
person.lists=a,b,c,1,2,3
person.maps.k1=v1
person.maps.k2=20
person.dog.name=dog
person.dog.age=7

4. @Value获取值和@ConfigurationProperties获取值比较

@ConfigurationProperties 支持松散语法绑定; 在properties文件中可以用 - 后跟随小写字母来表示-后大写字母

@Value("${first-name}") ; person.first-name;

@Value 不支持JSR303校验;

@Email

@Value不支持复杂类型封装;比如Map比如Object类型

配置文件yml还是properties都可以获取值,如果只需要在某个业务逻辑中获取配置文件中某个值则使用@Value

如果专门编写了一个javaBean来和配置文件进行映射,则使用@configurationProperties;\

5.@PropertySource 加载指定配置文件

@Component
@ConfigurationProperties(prefix = "person")
@PropertySource(value="classpath:person.properties")  //使用此注解来读取指定的配置文件
public class Person {

    /**
     * <bean id="" class="com.tree.Bean.Person">
     *  <property name="lastName" value="字面量"/${key}从环境变量、配置文件中获取值/#{Spel}></property>
     * </bean>
     */
//    @Value("${person.last-name}")
    private String lastName;
//    @Value("#{11}")
    private Integer age;
//    @Value("true")
    private Boolean boos;
//    @Value("${person.birth}")
    private Date birth;

6 @ImportResource :导入Spring的配置文件,让配置文件内容生效;

spring boot里面没有spring的配置文件,我们自主编写的配置文件,也不能自动识别;

如果需要在spring boot中使用 自主编写的spring配置文件,则需要在启动类添加@ImportResource注解;

@ImportResource(locations = "classpath:beans.xml")
@SpringBootApplication
public class SpringbootApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootApplication.class, args);
	}

}


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean id="helloService" class="com.tree.springboot.service.HelloService">

        </bean>
</beans>

SpringBoot推荐给容器中添加组件的方式:推荐使用全注解的方式

1.配置类====spring配置文件

2.使用@Bean给容器中添加组件

/**
 * @configuration 指明当前类是一个配置类;用来替代之前spring配置文件
 * 在配置文件中使用<bean></bean> 用来添加组件
 */
@Configuration
public class MyAppConfig {
    /**
     * 将方法的返回值添加到容器中;容器中这个组件默认Id就是方法名;
     * @return
     */
    @Bean
    public HelloService helloService(){
        System.out.println("配置类,给容器中添加组件");
        return new HelloService();

    }

}

7.配置文件占位符:

1.随机数

2.占位符获取之前配置的值,如果没有则指定默认值:

person.age=12
person.birth=2020/7/7
person.boos=true
person.last-name=张三${random.uuid}
person.lists=a,b,c,1,2,3
person.maps.k1=v1
person.maps.k2=${person.last-name}
person.dog.name=${person.hello:hello}_dog
person.dog.age=${random.int}

8.Profile

  1. 多Profile文件

    我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml

    默认使用application.properties

    如果需要激活其他配置文件则需要在主配置文件中添加:

    spring.profiles.active=dev
    
    
  2. yml支持多文档快方式

    server:
      port: 8081
    spring:
      profiles:
        active: prod
    ---
    server:
      port: 8082
    spring:
      profiles: dev
    ---
    server:
      port: 8283
    spring:
      profiles: prod
    ---
    
    

    该方式将yml分割成多个文档块,然后由首块进行选择配置

  3. 命令行的方式激活文档

    –spring.profiles.active=dev
    可以于配置界面进行配置,还可以于打包后于cmd中使用

    java -jar xxx.jar --spring.profiles.active=prod

    虚拟机参数

    -Dspring.profiles.active=dev

9 配置文件加载位置:

-file:./config/

-file:./

-classpath:/config/

-classpath:/

优先级从上往下,springboot会从这四个位置加载主配置文件;互补配置

我们可以通过spring.config.loacation来改变默认的配置文件位置

java -jar xxx.jar --spring.config.loacation=d:/xxx.properties

10 外部配置加载顺序

springboot也可以从以下位置加载配置;优先级从高到底;高优先级会覆盖低优先级配置,所有配置会形成互补配置;

  1. 命令行参数

    java -jar xxx.jar --server.port=8087

  2. 来自java:comp/env的NDI属性

  3. java系统属性 System.getProperties()

  4. 操作系统环境变量

  5. RandomValueProperrySource配置的random.* 属性值

    优先加载带profie,再加载不带profile 由jar包外向jar包内进行寻找

  6. jar包外部的application-{profile}.properties或application.yml 带spring.profile配置文件

  7. jar包内部的application-{profile}.properties或application.yml 带spring.profile配置文件

  8. jar包外部的application.properties或application.yml 不带spring.profile配置文件

  9. jar包内部的application.properties或application.yml 不带spring.profile配置文件

  10. @Configuration注解类上的@PropertySource

  11. 通过springApplication.setDefaultProperties指定的默认属性

九.springboot 自动配置

  1. springboot启动会加载大量的自动配置类,自动配置类会从properties文件中读取各类默认值。
  2. springboot有没有提供我们需要的的自动配置类
  3. 如果有,只需要看这些自动配置类中存在哪些组件;
  4. 给容器中自动配置类添加组件时,会从properties类中获取某些属性。我们则可以在配置文件中指定这些属性的值。

xxxAutoConfiguration:自动配置类;给容器中个天价组件

xxxxproperties:封装配置文件中相关属性;

自动配置类必须在一定的条件下才能生效;

debug=true #开启springboot Debug模式

============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)
Negative matches:
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

   AopAutoConfiguration.AspectJAutoProxyingConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)


十 springboot日志框架

springboot选用SLF4J和logback;

##SLF4J的使用:

在开发中,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

在使用日志框架时,需要导入SLf4j.jar 以及 slf4j实现jar 比如logback.jar 在使用一些不是直接实现slf4j的日志框架时,需要导入适配jar。具体见:

http://www.slf4j.org/manual.html

配置文件使用实现框架本身的配置文件;

如果在多个框架中想要整合多个框架用SLF4j进行日志输出,则需要使用适配jar替换原有日志jar包;

具体见:

http://www.slf4j.org/legacy.html

slf4j替换其他日志框架

在这张图片中,可以看到slf4j提供了解决一个应用多个日志框架并存的解决方案;

由jcl-over.slf4j.jar log4j-over.slf4j.jar …替换掉原有的commons logging.jar log4j.jar…,这样就解决了多个日志框架并存的问题;

springboot能自动适配所有的日志,地城是用slf4j+logback的方式记录日志,引入其他框架时,需要把这个框架依赖的日志框架排除掉;

日志使用

@SpringBootTest
public class SpringbootApplicationTests {

	//日志记录器
	Logger logger = LoggerFactory.getLogger(getClass());

	@Test
	void serviceTest(){
		//日志的级别,由低到高
		logger.trace("这是trace日志信息");
		logger.debug("这是debug信息");
		logger.info("这是info信息");
		logger.warn("这是warn信息");
		logger.error("这是error信息");
    }

在主配置文件中可调整输出级别;

logger.level.com.tree.springboot=trace

logging.file.path=/spring/log   //在指定位置生成默认spring.log文件

日志输出格式:

logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS}{%thread}%-5level %logger{50} - %msg%n
#在文件中输出日志的格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS}==={%thread}%-5level ===%logger{50} - %msg%n

指定配置:

在类路径下部署自己的配置文件即可;springboot就不使用默认配置文件;

具体可查springboot官方文档;

日志切换:

排除掉原来的logging-starter 使用新的日志starter

十一 web开发

添加模板引擎:

<!--		添加thymeleaf模板引擎组件-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";
    //只要根据配置将模板放在对应目录下,则会进行自动渲染


模板引擎使用:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:text="${hello}"></div>
</body>
</html>

3.模板引擎语法规则

  1. th:text;改变当前元素里面的文本内容

    th:任意html属性 ;替换原有属性值;

  2. 表达式:

    1. 获取属性、调用方法;
    2. 获取内置基本对象;
    3. 内置的一些工具对象:

十二.如何修改springboot默认配置

模式:

  • springboot在自动配置很多组件的时候,会先看容器中是否有用户自己配置的(@Bena @Component) 如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置和默认的组合起来;
  • 在springboot中会有xxxCustomizer帮助我们进行定制配置

十三 国际化

  1. 添加国际化文件

  2. 添加国际化文件地址:

    #国际化文件配置地址
    spring.messages.basename=i18n.login
    
    
  3. 页面获取国际化值

    th:text="#{login.username}"
    th:text="#{login.passowrd}"
    如果是button使用行内表达式
    [[#{login.rember}]]
    
    

4.点击链接切换国际化

package com.tree.springboot.component;

import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * 可以在链接上携带区域信息
 */
public class MyLocalResolver  implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
       String l= httpServletRequest.getParameter("l");
       //获取系统默认地址信息
       Locale local=Locale.getDefault();
       if(!StringUtils.isEmpty(l)) {
           String[] split = l.split("_");
           local=new Locale(split[0],split[1]);
       }
        return local;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}



package com.tree.springboot.config;


import com.tree.springboot.component.MyLocalResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("hello");
    }
	//往容器中添加我们写的配置类
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocalResolver();
    }
}


4.登录错误消息表达式

<p style="color:red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

如果msg不为空则生成p标签;

  1. 拦截器
package com.tree.springboot.component;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginHandlerInterceptor  implements HandlerInterceptor {
    //目标方法执行之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       Object user=request.getSession().getAttribute("abc");
       if(user == null){
           request.setAttribute("msg","没有权限,请先登录");
           request.getRequestDispatcher("/index.html").forward(request,response);
           return false;
       }else{
           return true;
       }

    }
}


定义拦截组件

  @Override
    public void addInterceptors(InterceptorRegistry registry) {
            //此拦截器拦截除login./...等的其他请求
            registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/user/login");
    }


注册拦截器

十四、公共片段抽取

定义和引用片段

<!DOCTYPE html>

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

  <body>
  
    <div th:fragment="copy">
      &copy; 2011 The Good Thymes Virtual Grocery
    </div>
  
  </body>
  
</html>

上面的代码定义了一个片段copy,我们可以使用th:insert或th:replace属性之一轻松地将其包含在主页中(并且th:include,尽管从Thymeleaf 3.0开始不再建议使用它):

<body>

  ...

  <div th:insert="~{footer :: copy}"></div>
  
</body>

th:insertth:replace(和th:include)之间的差异

和之间有什么区别th:insertth:replace(和th:include,因为3.0不推荐)?

  • th:insert 最简单:它将简单地将指定的片段作为其host标签的主体插入。
  • th:replace实际上其主机标签替换为指定的片段。
  • th:include与相似th:insert,但不插入片段,而是仅插入该片段的内容

因此,HTML片段如下所示:

<footer th:fragment="copy">
  &copy; 2011 The Good Thymes Virtual Grocery
</footer>

…在主机``标签中包含了3次,如下所示:

<body>

  ...

  <div th:insert="footer :: copy"></div>

  <div th:replace="footer :: copy"></div>

  <div th:include="footer :: copy"></div>
  
</body>

…将导致:

<body>

  ...

  <div>
    <footer>
      &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
  </div>

  <footer>
    &copy; 2011 The Good Thymes Virtual Grocery
  </footer>

  <div>
    &copy; 2011 The Good Thymes Virtual Grocery
  </div>
  
</body>

三种引入公共片段的方式:

th:insert: 插入到声明引入的元素

th:replace 替换为公共片段

th:include 将被引入的片段内容包含进这个标签中

引入片段传入参数

  • 将要引入的html片段抽取出来,单独创建一个html并标记为公共片段

  • 将公共片段引入到页面中

  • <th:class="${activeUri==‘main.html’?‘nav-link active’:'nav-link}"

  • <div th:replace="commons/bar::#sidebar(activeUri='emp')"></div>
    
    

发送put请求(ruest风格)

  1. springMVC配置hiddenHttpMethodFilter(springboot自动配置好的)
  2. 创建一个post表单
  3. 创建一个input项,name=“_method” 值就是我们制定的请求方式
<input type="hidden" name="_method" value="put" th:if=${emp!=null}>
<input type="hidden" name="_method" value="delete" th:if=${emp!=null}>

put请求:适合于修改页面

delete请求:适用于删除操作页面

<a th:${if:}></a>>

定制错误页面

原理:可以 参照ErrorMvcAutoConfiguation;

给容器中添加了如下组件:

  1. ErrorPageCustomizer
  2. BasicErrorController:处理错误请求
  3. ErrorPageCustomizer:系统出现错误以后,来到error请求进行处理;
  4. DefaultErrorViewResolver: 页面控制

步骤:系统发生错误:ErrorPageCustomizer生效,定制错误响应规则,接着来到BasicErrorController,

定制错误响应:
  1. 有模板引擎的情况下:

    在resource下thymelaeaf文件夹下 创建error文件夹,并创建404错误页面。

    如果没有匹配的指定错误,则创建4xx.html匹配其他以4开头的错误

    页面能获取的信息:

    timestamp:时间戳

    status:状态码

    error:错误提示

    exception:异常对象

    message:异常消息

    errors: JSR303数据校验错误

  2. 没有模板引擎:在静态资源文件夹下找error文件夹,并找寻错误页面

  3. 定制错误json数据;

    @ControllerAdvice
    public class MyExceptionHandler {
        @ResponseBody
        @ExceptionHandler(UserNotExistException.class)
        public Map<String,Object> handleException(Exception e   ){
            Map<String,Object> map=new HashMap<String,Object>();
            map.put("code","user.notexits");
            map.put("message",e.getMessage());
            return map;
        }
    }
    //没有自适应效果,浏览器与客户端返回的都是json
    
    
     @ExceptionHandler(UserNotExistException.class)
        public String handleException(Exception e, HttpServletRequest request){
            Map<String,Object> map=new HashMap<String,Object>();
            //传入错误状态码
            request.setAttribute("javax.servlet.error.status_code",400);
            map.put("code","user.notexits");
            map.put("message",e.getMessage());
            //转发值springboot默认错误处理控制器
            return "forward:/error";
        }
    
    

    出现错误以后,回来到/error请求,会被BasicErrorControlloer处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorContorller)规定的方法);

    完全编写一个ErrorController实现类,放在容器中;将由我们自己控制错误处理请求;

    页面上能用的数据,或者是json返回能用的数据都是通过erroeAttributes.getErrorAttributes得到的;

    容器中DefaultErrorAttrributes.getErrorAttributes();默认进行数据处理;

    自定义ErrorAttributes

    //给容器中添加自定义errorAttributes
    @Component
    public class MyErrorAttributes extends DefaultErrorAttributes {
        @Override
        public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
            Map<String,Object> map=super.getErrorAttributes(webRequest,includeStackTrace);
            //天机错误信息
            map.put("company","tree");
    
            return map;
        }
    }
    
    
    

十五 配置嵌入式servlet

Springboot默认是用的嵌入式的servlet;

如何定制和修改servlet容器的相关配置

修改和server有关的配置

server.port=8080
#spring.profiles.active=dev
#用于配置项目访问路径
server.servlet.context-path=crud
//通用的servlet容器设置
server.xxxx
//tomcat的设置
server.tomcat.xxx
server.tomcat.accesslog.encoding=utf-8

public class ServerPropertiesServerProperties 
    //类用来配置servlet相关配置;

2.编写一个EmbeddedServletContainerCustomizer嵌入式的servlet容器定制器,来修改servlet配置;

3.注册servlet三大组件

由于springboot默认是以jar包的方式启动嵌入式的servlet容器来启动springboot的web应用,没有web.xml所以我们使用:

  //注册三大组件
    @Bean
    public ServletRegistrationBean myServlet(){
        //映射servlet请求,当发出myServlet请求时,就会来到这个servlet
        ServletRegistrationBean servletRegistrationBean=  new ServletRegistrationBean(new MyServlet(),"/myServlet");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter());
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));

        return filterRegistrationBean;
    }


    @Bean
    public ServletListenerRegistrationBean myListener(){
        ServletListenerRegistrationBean servletListenerRegistrationBean=new ServletListenerRegistrationBean<MyListener>(new MyListener());
        return servletListenerRegistrationBean;
    }

springboot帮我们自动注册springMVC的时候,自动的注册springmvc前端控制器,DispatcherServlet;

springMVC默认拦截所有,但是不拦截jsp请求; /*会拦截jsp

可以通过server.servletPath来修改springmvc前端控制器默认拦截的请求路径;

springboot能不能支持其他的servlet容器;

默认支持:Tomcat Jetty Undertow

引入别的容器:

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<artifactId>spring-boot-starter-tomcat</artifactId>
					<groupId>org.springframework.boot</groupId>
				</exclusion>
			</exclusions>
		</dependency>

		<!--		引入别的容器-->
		<dependency>
			<artifactId>spring-boot-starter-jetty</artifactId>
			<groupId>org.springframework.boot</groupId>
		</dependency>


? 部分注解

@ResponseBody

@Controller

以上两个注解等同于 @RestController

@Conditional

必须是@Condiiional 注解指定的条件成立,才能给容器中添加组件

@PostMapping(value=" ")

@RequestParam(" ")

@GetMapping("/emp/{id}")

public String toEditPage(@PathVariable(“id”) Integer id){

}

@PathVariable(""): 路径变量

记录

StringUtils()方法:

"redirect:重定向页面

"forward: 转发页面


版权声明:本文为wangxulei123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>