SpringBoot

SpringBoot

第一章 JavaConfig

  1. 为什么要使用 Spring Boot

    因为Spring, SpringMVC 需要使用的大量的配置文件 (xml文件)

    还需要配置各种对象,把使用的对象放入到spring容器中才能使用对象

    需要了解其他框架配置规则。

  2. SpringBoot 就相当于 不需要配置文件的Spring+SpringMVC。 常用的框架和第三方库都已经配置好了。

    拿来就可以使用了。

  3. SpringBoot开发效率高,使用方便多了

SpringBoot基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。

SpringBoot所具备的特征有:

(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;

(2)内嵌Tomcat或Jetty等Servlet容器;

(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;

(4)尽可能自动配置Spring容器;

(5)提供准备好的特性,如指标、健康检查和外部化配置;

(6)绝对没有代码生成,不需要XML配置。 [1] [2]

总而言之:springboot就是化繁为简

1.1 JavaConfig

JavaConfig: 使用java类作为xml配置文件的替代, 是配置spring容器的纯java的方式。 在这个java类这可以创建java对象,把对象放入spring容器中(注入到容器),

使用两个注解:

1)@Configuration : 放在一个类的上面,表示这个类是作为配置文件使用的。替代xml文件

2)@Bean:声明对象,把对象注入到容器中。

例子:
package com.bjpowernode.config;

import com.bjpowernode.vo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Configuration:表示当前类是作为配置文件使用的。 就是用来配置容器的
 *       位置:在类的上面
 *
 *  SpringConfig这个类就相当于beans.xml
 */
@Configuration
public class SpringConfig {

    /**
     * 创建方法,方法的返回值是对象。 在方法的上面加入@Bean
     * 方法的返回值对象就注入到容器中。
     *
     * @Bean: 把对象注入到spring容器中。 作用相当于<bean>
     *
     *     位置:方法的上面
     *
     *     说明:@Bean,不指定对象的名称,默认是方法名是 <bean id  />
     		 Student s2 = (Student) ac.getBean("方法名");
     *
     */
    @Bean 
    public Student createStudent(){
        Student s1  = new Student();
        s1.setName("张三");
        s1.setAge(26);
        s1.setSex("男");
        return s1;
    }


    /***
     * 指定对象在容器中的名称(指定<bean>的id属性)
     * @Bean的name属性,指定对象的名称(id)
     */
    @Bean(name = "lisiStudent")/@Bean("lisiStudent")
    public Student makeStudent(){
        Student s2  = new Student();
        s2.setName("李四");
        s2.setAge(22);
        s2.setSex("男");
        return s2;
    }
}


测试类:
    
     	ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student s2 = (Student) ac.getBean("lisiStudent");

        System.out.println(s2);

采用xml创建bean对象:

ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

采用类创建bean对象:

ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
@Bean(name = "lisiStudent")/@Bean("lisiStudent")
    public Student makeStudent(){
        Student s2  = new Student();
        s2.setName("李四");
        s2.setAge(22);
        s2.setSex("男");
        return s2;
    }

等价于配置文件xml中
    <bean id="lisiStudent" class="com.lebrwcd.domain.Student">
        <property name="name" value="李四"/>
        <property name="sex" value="男"/>
        <property name="age" value="22"/>
    </bean>
        
 最终的作用都是声明bean,把bean注入到容器中

1.2 @ImporResource

@ImportResource 作用导入其他的xml配置文件, 等于 在xml

<import resources="其他配置文件"/>

例如:

@Configuration
@ImportResource(value ={ "classpath:applicationContext.xml","classpath:beans.xml"})
public class SpringConfig {
}

使用@ImportResource之后可以导入其他的xml配置文件,可以使用导入进来的配置文件中的bean

@Configuration
@ImportResource("classpath:beans.xml")
public class SpringConfig {

    @Bean("MyStudent")
    public Student createStudent(){

        Student s1 = new Student();
        s1.setName("zpp");
        s1.setAge(16);
        s1.setSex("女");
        return s1;
    }
}
<?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="Student" class="com.lebrwcd.domain.Student">
        <property name="name" value="wcd"/>
        <property name="sex" value=""/>
        <property name="age" value="18"/>
    </bean>

    <bean id="MyCat" class="com.lebrwcd.domain.Cat">
        <property name="name" value="tom"/>
        <property name="age" value="2"/>
    </bean>

</beans>

导入beans.xml之后,就相当于SpringConfig这个配置类有了其他的bean,可以直接拿来使用

@org.junit.Test
public void test03(){

    ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
    Cat cat = (Cat) ac.getBean("MyCat");
    System.out.println("Cat=" + cat);
}

1.3 @PropertyResource

@PropertyResource: 读取properties属性配置文件。 使用属性配置文件可以实现外部化配置 ,

在程序代码之外提供数据。

步骤:

  1. 在resources目录下,创建properties文件, 使用k=v的格式提供数据
  2. 在PropertyResource 指定properties文件的位置
  3. 使用@Value(value="${key}")

属性资源配置文件.properties使用中文

image-20220216214540041

1.创建老虎类

2.创建属性资源配置文件写上k和v

3.采用注解的方式创建bean,@Component

4.采用@Value的方式给类属性赋值

5.SpringConfig配置类需要加上@ComponetScan和@PropertySource

@Component("tiger")   //相当于xml配置文件中bean标签的id
public class Tiger {
    @Value("${tiger.name}")  //@Value("${key}")
    private String name;
    @Value("${tiger.age}")
    private Integer age;
tiger.name=胖虎
tiger.age=4
@Configuration
@ImportResource("classpath:beans.xml")
@ComponentScan(basePackages = "com.lebrwcd.domain")   //扫描注解-Component注入bean到容器中
@PropertySource(value = "classpath:kv.properties")
public class SpringConfig {
    
}
加上@Configuration注解,那么该类就是一个配置类,起到xml配置文件的作用
    @ImportResource == <import resource=".." />
    @ComponentScan(basePackages = "..") == <context:component-scan base-package=".."/>
    @PropertySource(value = "..") == <context:property-placeholder location = ".." />
@org.junit.Test
public void test04(){

    ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
    Tiger tiger = (Tiger) ac.getBean("tiger");
    System.out.println("tiger=" + tiger);
}

//tiger=Tiger{name='胖虎', age=4}

第二章 Spring Boot

2.1 介绍

SpringBoot是Spring中的一个成员, 可以简化Spring,SpringMVC的使用。 他的核心还是IOC容器。

特点:

  • Create stand-alone Spring applications

    创建spring应用

  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

    内嵌的tomcat, jetty , Undertow

  • Provide opinionated ‘starter’ dependencies to simplify your build configuration

    提供了starter起步依赖,简化应用的配置。

    比如使用MyBatis框架 , 需要在Spring项目中,配置MyBatis的对象 SqlSessionFactory , Dao的代理对象

    在SpringBoot项目中,在pom.xml里面, 加入一个 mybatis-spring-boot-starter依赖

  • Automatically configure Spring and 3rd party libraries whenever possible

    尽可能去配置spring和第三方库。叫做自动配置(就是把spring中的,第三方库中的对象都创建好,放到容器中, 开发人员可以直接使用)

  • Provide production-ready features such as metrics, health checks, and externalized configuration

    提供了健康检查, 统计,外部化配置

  • Absolutely no code generation and no requirement for XML configuration

    不用生成代码, 不用使用xml文件做配置

2.2 创建Spring Boot项目

2.2.1 第一种方式, 使用Spring提供的初始化器, 就是向导创建SpringBoot应用

使用的地址: https://start.spring.io

注:需要在有网环境下

image-20220216222107416 image-20220216222238368

SpringBoot项目的结构:

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

创建完之后的pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <!--Springboot的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <!--当前项目的gav-坐标-->
    <groupId>com.example</groupId>
    <artifactId>springboot-first</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <!--向导创建时设置的-->
    <name>002-springboot-first</name>
    <description>Demo project for Spring Boot</description>
    
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.3</version>
            </plugin>
        </plugins>
    </build>

</project>

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

2.2.1 使用国内的地址

https://start.springboot.io

image-20220217114146885

2.2.2 使用springboot的web

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

运行springboot的Application[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5Zsk3Wp-1647521439152)(C:/Users/Lebr7Wcd/AppData/Roaming/Typora/typora-user-images/image-20220217115950281.png)]

通过main方法启动springboot项目

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

springBoot让我们更加专注于业务代码Controller层,service层的编写,其余web配置基本都帮我们配置好了

2.3 注解的使用

@SpringBootApplication

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//上面4个是元注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

是一个复合注解,由

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan 组合而成

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

1.@SpringBootConfiguration

@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

//@Configuration 注解是可以将该类注意配置来使用的

说明:**使用了@SpringBootConfiguration注解标注的类,可以作为配置文件使用****的,可以使用Bean声明对象,注入到容器

2.@EnableAutoConfiguration

启用自动配置, 把java对象配置好,注入到spring容器中。例如可以把mybatis的对象创建好,放入到容器中

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

3.@ComponentScan

@ComponentScan 扫描器,找到注解,根据注解的功能创建对象,给属性赋值等等
默认扫描的包: @ComponentScan所在的类所在的包和子包。

为什么前面我们编写@Controller的时候不用写组件扫描器呢?因为@ComponentScan在Application类的注解

@SpringBootApplication中,而@ComponentScan默认扫描的包在Application类的包以及其子包

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

2.4 SpringBoot的配置文件

配置文件名称: application

扩展名有: properties( k=v) ; yml ( k: v)

使用application.properties, application.yml

例1:application.properties设置 端口和上下文

#设置端口号
server.port=8081
#设置访问上下文路径
server.servlet.context-path=/myboot

设置完之后重新启动application中的main方法

@SpringBootApplication
public class Application {

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

}

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

例2: application.yml

k:空格 v

server:

空格(下一级)

server:
  port: 8080
  servlet:
    context-path: /myboot2

IDEA中敲回车自动有空格

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

同时存在上面两个配置文件时(默认使用.properties的),只能有一个名为application的配置文件,然后maven刷新

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

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

2.5 多环境配置

有开发环境, 测试环境, 上线的环境。

每个环境有不同的配置信息, 例如端口, 上下文件, 数据库url,用户名,密码等等

使用多环境配置文件,可以方便的切换不同的配置。

使用方式: 创建多个配置文件, 名称规则: application-环境名称.properties(yml)

创建开发环境的配置文件: application-dev.properties( application-dev.yml )

创建测试者使用的配置: application-test.properties

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

在springboot的核心配置文件中选择指定哪个环境的配置:

spring:
 profiles:
   active: 填application-之后的字母

2.6 @ConfigurationProperties

@ConfigurationProperties: 把配置文件的数据映射为java对象。

属性:prefix 配置文件中的某些key的开头的内容。

prefix 可以不指定,如果不指定,那么 会去配置文件中寻找与该类的属性名一致的配置,prefix 的作用可以区分同名配置


@Component   //加Component注解将这个对象注入到容器中,为了后续Controller层  对该对象采用自动注入的方式获取该bean对象
			 //@Resource
			 //private SchoolInfo info
@ConfigurationProperties(prefix = "school")
public class School {

    private String name;  //属性名要和配置文件中的prefix.后面的一致

    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

application.properties

server.port=8081
server.servlet.context-path=/myschool
school.name=广州软件学院
school.address=广州从化
image-20220217215710712

出现警告的解决方法:

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

点击 open documentnation 跳转到网页,在网页中提示需要加一个依赖,我们将这个依赖拷贝, 粘贴到 pom.xml 文件中

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

<<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
 </dependency>

2.7 使用jsp(了解)

SpringBoot不推荐使用jsp ,而是使用模板技术代替jsp

使用jsp需要配置:

1) 加入一个处理jsp的依赖。 负责编译jsp文件

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
  1. 如果需要使用servlet, jsp,jstl的功能
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
	<artifactId>javax.servlet.jsp-api</artifactId>
	<version>2.3.1</version>
</dependency>

  1. 创建一个存放jsp的目录,一般叫做webapp

​ index.jsp

  1. 需要在pom.xml指定jsp文件编译后的存放目录。

META-INF/resources

5)创建Controller, 访问jsp

6)在application.propertis文件中配置视图解析器

2.8 使用容器

你想通过代码,从容器中获取对象。

通过SpringApplication.run(Application.class, args); 返回值获取容器。

主方法中的run()方法的返回值就是容器对象


public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
}

ConfigurableApplicationContext : 接口,是ApplicationContext的子接口
public interface ConfigurableApplicationContext extends ApplicationContext  容器对象
@SpringBootApplication
public class Application {

    public static void main(String[] args) {


        //获取容器对象
        ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);

        //从容器从获取对象
        UserService userService = (UserService) ctx.getBean("userService");
        userService.sayHello("詹篇篇");
    }

}
//詹篇篇say :Hello


@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void sayHello(String name) {
        System.out.println(name +"say :Hello");
    }
}

获取容器对象,一般用在需要测试哪个sercice接口中的方法,获取serviceimpl的bean对象进行测试

2.9 ComnandLineRunner 接口 , ApplcationRunner接口

开发中可能会有这样的情景。需要在容器启动后执行一些内容。比如读取配置文件,数 据库连接之类的。SpringBoot 给我们提供了两个接口来帮助我们实现这种需求。这两个接口 分别为 CommandLineRunner 和 ApplicationRunner。他们的执行时机为容器启动完成的时候。 这两个接口中有一个 run 方法,我们只需要实现这个方法即可。这两个接口的不同之处 在于: ApplicationRunner 中 run 方 法 的 参 数 为 ApplicationArguments , 而 CommandLineRunner 接口中 run 方法的参数为 String 数组

这两个接口都 有一个run方法。 执行时间在容器对象创建好后, 自动执行run()方法。

可以完成自定义的在容器对象创建好的一些操作。

@FunctionalInterface
public interface CommandLineRunner {
    void run(String... args) throws Exception;
}

@FunctionalInterface
public interface ApplicationRunner {
    void run(ApplicationArguments args) throws Exception;
}

IDEA中"ctrl + i "实现接口方法

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Resource
    private UserService userService;

    public static void main(String[] args) {

        System.out.println("准备创建容器对象==============");
        //获取容器对象
        SpringApplication.run(Application.class, args);

        System.out.println("创建好了容器对象=============");

    }

    @Override
    public void run(String... args) throws Exception {

        userService.sayHello("吴楚典");
        System.out.println("执行了CommandLineRunner中的run方法");
    }
}
准备创建容器对象==============

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.3)

2022-02-19 12:32:18.916  INFO 11744 --- [           main] com.lebrwcd.Application                  : Starting Application using Java 1.8.0_152 on LeBrWcd with PID 11744 (D:\IntelliJ IDEA\IntelliJ IDEA 2021.1.1\projeces\SpringBoot\003-springboot-configproper\target\classes started by Lebr7Wcd in D:\IntelliJ IDEA\IntelliJ IDEA 2021.1.1\projeces\SpringBoot)
2022-02-19 12:32:18.920  INFO 11744 --- [           main] com.lebrwcd.Application                  : No active profile set, falling back to default profiles: default
2022-02-19 12:32:20.369  INFO 11744 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2022-02-19 12:32:20.370  INFO 11744 --- [           main] o.a.catalina.core.AprLifecycleListener   : Loaded Apache Tomcat Native library [1.2.30] using APR version [1.7.0].
2022-02-19 12:32:20.371  INFO 11744 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
2022-02-19 12:32:20.371  INFO 11744 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2022-02-19 12:32:20.376  INFO 11744 --- [           main] o.a.catalina.core.AprLifecycleListener   : OpenSSL successfully initialized [OpenSSL 1.1.1k  25 Mar 2021]
2022-02-19 12:32:20.388  INFO 11744 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-02-19 12:32:20.388  INFO 11744 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-02-19 12:32:20.579  INFO 11744 --- [           main] o.a.c.c.C.[.[localhost].[/myschool]      : Initializing Spring embedded WebApplicationContext
2022-02-19 12:32:20.580  INFO 11744 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1587 ms
2022-02-19 12:32:21.198  INFO 11744 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path '/myschool'
2022-02-19 12:32:21.210  INFO 11744 --- [           main] com.lebrwcd.Application                  : Started Application in 2.939 seconds (JVM running for 4.558)
吴楚典say :Hello
执行了CommandLineRunner中的run方法
创建好了容器对象=============

可以看出,如果实现了CommandLineRunner接口,在创建完容器对象过程中,会调用CommmandLineRunner中的run方法,并且@Resource自动注入的对象已经赋完值了可以使用了,在CommandLinerRunner中的run方法,我们可以实现在创建容器对象过程中读取配置文件,加载数据库等操作(ApplicationRunner接口同理)

第三章 Web组件

讲三个内容: 拦截器, Servlet ,Filter

3.1 拦截器

拦截器是SpringMVC中一种对象,能拦截器对Controller的请求。

拦截器框架中有系统的拦截器, 还可以自定义拦截器。 实现对请求预先处理。

实现自定义拦截器:

  1. 创建类实现SpringMVC框架的HandlerInterceptor接口

    public interface HandlerInterceptor {
     
     //preHandle
     default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         return true;
     }
     //postHandle
     default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
     }
     //afterHandle
     default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
     }
    }
    

2.需在SpringMVC的配置文件中,声明拦截器

<mvc:interceptors>
	<mvc:interceptor>
    	<mvc:path="url" />
        <bean class="拦截器类全限定名称"/>
    </mvc:interceptor>
</mvc:interceptors>

SpringBoot中注册拦截器:

springBoot中注册拦截器需要实现WebConfigurer接口,这个接口都是与spingmvc有关的方法

public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }

    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }

    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }

    default void addFormatters(FormatterRegistry registry) {
    }

    default void addInterceptors(InterceptorRegistry registry) {  //注册拦截器
    }

    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

    default void addCorsMappings(CorsRegistry registry) {
    }

    default void addViewControllers(ViewControllerRegistry registry) {
    }

    default void configureViewResolvers(ViewResolverRegistry registry) {
    }

    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }

    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }

    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

注册拦截器的方法

addInterceptors(InterceptorRegistry registry) 
    参数:registry:拦截器注册中心

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

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

自定义拦截器对象

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行了preHandle方法");

        //放行控制器
        return true;  
    }
}

配置类

@SpringBootConfiguration
public class MyWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //创建拦截器对象
        HandlerInterceptor interceptor = new MyInterceptor();

        //指定请求拦截的url地址
        String[] path = {"user/*"};
        
        //指定请求不拦截的url地址
        String[] excluedPath = {"user/login"};

        //注册拦截器
        registry.addInterceptor(interceptor)
                .addPathPatterns(path)
                .excludePathPatterns(excluedPath);
    }
}

测试拦截器

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/account")
    @ResponseBody
    public String account(){
        return "访问/user/account地址";
    }

    @RequestMapping("/login")
    @ResponseBody
    public String login(){
        return "访问/user/login地址";
    }
}

在地址栏上敲:http://localhost:8080/user/login,由于我对这个请求没有拦截,所以这个请求拦截器不会拦截,也就不会执行preHandle方法;

image-20220219160541605

在地址栏上敲:http://localhost:8080/user/account,由于我对这个请求有拦截,所以这个请求拦截器会拦截,执行了preHandle方法

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

但是我自定义的拦截器写的返回值是true,所以执行了preHandle方法后依然会放行,浏览器上正常输出语句

image-20220219160602218

当我把自定义拦截器中的preHandle方法返回值改为false,效果就很明显了,/user/account被拦截,而/user/login不拦截

image-20220219160729398

3.2 Servlet

在SpringBoot框架中使用Servlet对象。

使用步骤:

  1. 创建Servlet类。 创建类继承HttpServlet
  2. 注册Servlet ,让框架能找到Servlet

例子:

1.创建自定义Servlet

//创建Servlet类
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //使用HttpServletResponse输出数据,应答结果
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out  = resp.getWriter();
        out.println("===执行的是Servlet==");
        out.flush();
        out.close();

    }
}
  1. 注册Servlet,把Servlet对象放入容器中
@Configuration
public class WebApplictionConfig {

    //定义方法, 注册Servlet对象,把Servlet对象放入容器中
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){

        //public ServletRegistrationBean(T servlet, String... urlMappings)
        //第一个参数是 Servlet对象, 第二个是url地址

        //ServletRegistrationBean bean =
                //new ServletRegistrationBean( new MyServlet(),"/myservlet");


        ServletRegistrationBean bean = new ServletRegistrationBean();
        bean.setServlet( new MyServlet()); //<Servlet-class>
        bean.addUrlMappings("/myservlet"); // <url-pattern>


        return bean; //@Bean注解的返回值是对象,该对象放入容器中
    }
}
image-20220219205154700

3.3 过滤器Filter

Filter是Servlet规范中的过滤器,可以处理请求, 对请求的参数, 属性进行调整。 常常在过滤器中处理字符编码

在框架中使用过滤器:

  1. 创建自定义过滤器类
  2. 注册Filter过滤器对象

例子:

// 自定义过滤器
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("执行过滤器中的doFilter方法");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);

    }
}

注册Filter

@Configuration
public class WebApplicationConfig {

    //注册过滤器Filter
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){

        FilterRegistrationBean bean = new FilterRegistrationBean();

        //设置过滤器
        bean.setFilter(new MyFilter());
        //添加过滤地址
        bean.addUrlPatterns("/student/*");

        return bean;  //返回bean对象放入容器中

    }
}

测试:

@Controller
public class TestController {

    @RequestMapping("/student/dofilter")
    @ResponseBody
    public String dofilter(){
        return "/student/dofilter";
    }

    @RequestMapping("/doSome")
    @ResponseBody
    public String doSome(){
        return "/doSome";
    }

}
image-20220219211106281

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

image-20220219211327339

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

3.4 字符集过滤器

CharacterEncodingFilter : 解决post请求中乱码的问题

在SpringMVC框架, 在web.xml 注册过滤器。 配置他的属性。

例子:

public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;");
        PrintWriter out = response.getWriter();
        out.print("执行了自定义Servlet中的post方法");
        out.flush();
        out.close();

    }
}
//注册Servlet
@Bean
public ServletRegistrationBean servletRegistrationBean(){

    ServletRegistrationBean reg = new ServletRegistrationBean();

    reg.setServlet(new MyServlet());
    reg.setLoadOnStartup(1);
    reg.addUrlMappings("/myservlet");

    return reg;

}
image-20220219214117674

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

默认编码:ISO-8859-1

采用字符集过滤器:

//注册字符集过滤器CharacterEncodingFilter
@Bean
public FilterRegistrationBean filterRegistrationBean(){
    FilterRegistrationBean reg = new FilterRegistrationBean();

    //创建字符集过滤器对象
    CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
    //设置编码方式
    encodingFilter.setEncoding("utf-8");
    //设置request,response的编码
    encodingFilter.setForceEncoding(true);

    reg.setFilter(encodingFilter);
    reg.addUrlPatterns("/*");

    return reg;
}

以上注册好了Filter之后,还是会出现乱码问题,原因是springboot框架本身就有使用字符集过滤器,只是它默认使用的是ISO-8859-1的编码格式,还需要在springboot核心配置文件中配置:

#SpringBoot中默认已经配置了CharacterEncodingFilter。 编码默认ISO-8859-1
#设置enabled=false 作用是关闭系统中配置好的过滤器, 使用自定义的CharacterEncodingFilter
server.servlet.encoding.enabled=false
image-20220219214554555

第一种方式:

使用步骤:

  1. 配置字符集过滤器

    @Configuration
    public class WebSystemConfig {
    
        //注册Servlet
        @Bean
        public ServletRegistrationBean servletRegistrationBean(){
            MyServlet myServlet = new MyServlet();
            ServletRegistrationBean reg = new ServletRegistrationBean(myServlet,"/myservlet");
            return reg;
        }
    
    
        //注册Filter
        @Bean
        public FilterRegistrationBean filterRegistrationBean(){
            FilterRegistrationBean reg = new FilterRegistrationBean();
    
            //使用框架中的过滤器类
            CharacterEncodingFilter filter  = new CharacterEncodingFilter();
            //指定使用的编码方式
            filter.setEncoding("utf-8");
            //指定request , response都使用encoding的值
            filter.setForceEncoding(true);
    
            reg.setFilter(filter);
            //指定 过滤的url地址
            reg.addUrlPatterns("/*");
    
    
            return reg;
        }
    }
    
  2. 修改application.properties文件, 让自定义的过滤器起作用

#SpringBoot中默认已经配置了CharacterEncodingFilter。 编码默认ISO-8859-1
#设置enabled=false 作用是关闭系统中配置好的过滤器, 使用自定义的CharacterEncodingFilter
server.servlet.encoding.enabled=false

第二种方式

修改application.properties文件

server.port=9001
server.servlet.context-path=/myboot

#让系统的CharacterEncdoingFilter生效
server.servlet.encoding.enabled=true
#指定使用的编码方式
server.servlet.encoding.charset=utf-8
#强制request,response都使用charset属性的值
server.servlet.encoding.force=true

第四章 ORM 操作 MySQL

使用MyBatis框架操作数据, 在SpringBoot框架集成MyBatis

使用步骤:

  1. mybatis起步依赖 : 完成mybatis对象自动配置, 对象放在容器中

  2. pom.xml 指定把src/main/java目录中的xml文件包含到classpath中

  3. 创建实体类Student

    public class Student {
    
        private Integer id;
        private String name;
        private Integer age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
  4. 创建Dao接口 StudentDao , 创建一个查询学生的方法

    /**
    *	@Mapper:告诉mybatis框架这是dao接口,创建此接口的代理对象。
    */
    @Mapper
    public interface StudentDao {
    
        Student QueryStudentByID(@Param("stuId")Integer id);
    
    }
    
  5. 创建Dao接口对应的Mapper文件, xml文件, 写sql语句

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.lebrwcd.dao.StudentDao">
        <select id="QueryStudentByID" resultType="com.lebrwcd.domain.Student">
            select *
            from tbl_student
            where id=#{stuId}
      </select>
    </mapper>
    
  6. 创建Service层对象, 创建StudentService接口和他的实现类。 去dao对象的方法。完成数据库的操作

    public interface StudentService {
        Student queryStudent(Integer id);
    }
    
    @Service
    public class StudentServiceImpl implements StudentService {
    
        @Resource
        private StudentDao studentDao;
    
    
        @Override
        public Student queryStudent(Integer id) {
            return studentDao.QueryStudentByID(id);
        }
    }
    
  7. 创建Controller对象,访问Service。

    @Controller
    public class StudentController {
    
        @Resource
        private StudentService studentService;
    
    
        @RequestMapping("/student/query")
        @ResponseBody
        public String query(Integer id){
    
            //通过参数id连接数据库查询学生信息
            Student student = studentService.queryStudent(id);
            return student.toString();
        }
    
    }
    
  8. 写application.properties文件

    配置数据库的连接信息。

    server.servlet.context-path=/orm
    #配置连接数据库
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=wcd0209  //不加报错
    spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    
    #datasource.url=jdbc:mysql://IP:端口/数据库名
    
  9. 测试:

    image-20220220153908553
<!--web起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--mybatis起步依赖-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    <version>8.0.25</version>
</dependency>

 <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>  //将src/main/java其子包目录下的xml编译到classes文件夹中
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

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

第一种方式 : @Mapper

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Mapper {
}

@Mapper:放在dao接口的上面, 每个接口都需要使用这个注解。

/**
 * @Mapper:告诉MyBatis这是dao接口,创建此接口的代理对象。
 *     位置:在类的上面
 */
@Mapper
public interface StudentDao {

    Student selectById(@Param("stuId") Integer id);
}

缺点:dao接口太多比较繁琐,每个接口都需要加@Mapper

第二种方式 @MapperScan(常用)

放在主启动类的上面,属性basePackages:dao接口所在包的全限定名称,可以有多个

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends Annotation> annotationClass() default Annotation.class;

    Class<?> markerInterface() default Class.class;

    String sqlSessionTemplateRef() default "";

    String sqlSessionFactoryRef() default "";

    Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;

    String lazyInitialization() default "";

    String defaultScope() default "";
}
/**
 * @MapperScan: 找到Dao接口和Mapper文件
 *     basePackages:Dao接口所在的包名
 */
@SpringBootApplication
@MapperScan(basePackages = {"com.lebrwcd.dao","com.lebrwcd.mapper"})
public class Application {
}
image-20220220154844105

第三种方式: Mapper文件和Dao接口分开管理(推荐)

基于上面两种方式(二选一)进行管理

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

现在把Mapper文件放在resources目录下

1)在resources目录中创建子目录 (自定义的) , 例如mapper

2)把mapper文件放到 mapper目录中

3)在application.properties文件中,指定mapper文件的目录

#指定mapper文件的位置
mybatis.mapper-locations=classpath:mapper/*.xml
#指定mybatis的日志
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
image-20220220160714224
  1. 在pom.xml中指定 把resources目录中的文件 , 编译到目标目录中
<!--resources插件-->
<resources>
   <resource>
      <directory>src/main/resources</directory>
      <includes>
         <include>**/*.*</include>
      </includes>
   </resource>
</resources>

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

第四个 事务

Spring框架中的事务:

1) 管理事务的对象: 事务管理器(接口, 接口有很多的实现类)

​ 例如:使用Jdbc或mybatis访问数据库,使用的事务管理器:DataSourceTransactionManager

2 ) 声明式事务: 在xml配置文件或者使用注解说明事务控制的内容

​ 控制事务: 隔离级别,传播行为, 超时时间

3)事务处理方式:

​ 1) Spring框架中的**@Transactional**

​ 2) aspectj框架可以在xml配置文件中,声明事务控制的内容

SpringBoot中使用事务: 上面的两种方式都可以。

1)在业务方法的上面加入@Transactional , 加入注解后,方法有事务功能了。

2)明确的在 主启动类的上面 ,加入**@EnableTransactionManager**

ServiceImpl.java

/**
 * @Transactional: 表示方法的有事务支持
 *       默认:使用库的隔离级别, REQUIRED 传播行为; 超时时间  -1
 *       抛出运行时异常,回滚事务
 */
@Transactional
@Override
public int addStudent(Student student) {

    System.out.println("执行业务方法添加学生");

    int rows =  studentDao.addStudent(student);
    //rows代表sql语句执行成功对表结构修改的行数

    //抛一个运行时异常,回滚事务
    //int m = 10 / 0;

    return rows;
}
@SpringBootApplication
@MapperScan(basePackages = "com.lebrwcd.dao")
@EnableTransactionManagement    //事务管理器
public class Application {

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

}

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

image-20220221134809479

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

第五章 接口架构风格 —RESTful

接口: API(Application Programming Interface,应用程序接口)是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。

接口(API): 可以指访问servlet, controller的url, 调用其他程序的 函数

架构风格: api组织方式(样子)

就是一个传统的: http://localhost:9002/mytrans/addStudent?name=lisi&age=26

​ 在地址上提供了 访问的资源名称addStudent, 在其后使用了get方式传递参数。

5.1 REST

RESTful架构风格

1)REST : (英文: Representational State Transfer , 中文: 表现层状态转移)。

REST:是一种接口的架构风格和设计的理念,不是标准。

优点: 更简洁,更有层次

表现层状态转移:

​ 表现层就是视图层, 显示资源的, 通过视图页面,jsp等等显示操作资源的结果。

​ 状态: 资源变化

​ 转移: 资源可以变化的。 资源能创建,new状态, 资源创建后可以查询资源, 能看到资源的内容,

这个资源内容 ,可以被修改, 修改后资源 和之前的不一样。

2)REST中的要素:

用REST表示资源和对资源的操作。 在互联网中,表示一个资源或者一个操作。

资源使用url表示的, 在互联网, 使用的图片,视频, 文本,网页等等都是资源。

资源是用名词表示。

对资源:

​ 查询资源: 看,通过url找到资源。

​ 创建资源: 添加资源

​ 更新资源:更新资源 ,编辑

​ 删除资源: 去除

资源使用url表示,通过名词表示资源。

​ 在url中,使用名词表示资源, 以及访问资源的信息, 在url中,使用“ / " 分隔对资源的信息

​ http://localhost:8080/myboot/student/1001

使用http中的动作(请求方式), 表示对资源的操作(CURD)

GET: 查询资源 – sql select

​ 处理单个资源: 用他的单数方式

​ http://localhost:8080/myboot/student/1001

​ http://localhost:8080/myboot/student/1001/1

​ 处理多个资源:使用复数形式

​ http://localhost:8080/myboot/students/1001/1002

POST: 创建资源 – sql insert

​ http://localhost:8080/myboot/student

​ 在post请求中传递数据

<form action="http://localhost:8080/myboot/student" method="post">
	姓名:<input type="text" name="name" />
    年龄:<input type="text" name="age" />
  </form>

PUT: 更新资源 – sql update

<form action="http://localhost:8080/myboot/student/1" method="post">
 姓名:<input type="text" name="name" />
 年龄:<input type="text" name="age" />
      <input type="hidden" name="_method" value="PUT" />
</form>

DELETE: 删除资源 – sql delete

```xml

删除1的数据
```

需要的分页, 排序等参数,依然放在 url的后面, 例如

http://localhost:8080/myboot/students?page=1&pageSize=20

`

3) 一句话说明REST:

​ 使用url表示资源 ,使用http动作操作资源。

  1. 注解

@PathVariable : 从url中获取数据

@GetMapping: 支持的get请求方式, 等同于 @RequestMapping( method=RequestMethod.GET)

@PostMapping: 支持post请求方式 ,等同于 @RequestMapping( method=RequestMethod.POST)

@PutMapping: 支持put请求方式, 等同于 @RequestMapping( method=RequestMethod.PUT)

@DeleteMapping: 支持delete请求方式, 等同于 @RequestMapping( method=RequestMethod.DELETE)

@RestController: 复合注解, 是@Controller 和@ResponseBody组合。

​ 在类的上面使用@RestController , 表示当前类者的所有方法都加入了 @ResponseBody

  1. Postman : 测试工具

    使用Postman : 可以测试 get ,post , put ,delete 等请求

5.2 在页面中或者ajax中,支持put,delete请求

在SpringMVC中 有一个过滤器, 支持post请求转为put ,delete

过滤器: org.springframework.web.filter.HiddenHttpMethodFilter

作用: 把请求中的post请求转为 put , delete

实现步骤:

  1. application.properties(yml) : 开启使用 HiddenHttpMethodFilter 过滤器
  2. 在请求页面中,包含 _method参数, 他的值是 put, delete , 发起这个请求使用的post方式

第六章 Redis

Redis : 一个NoSQL数据库, 常用作 缓存使用 (cache)

Redis的数据类型: string , hash ,set ,zset , list

Redis是一个中间件: 是一个独立的服务器。

java中著名的客户端: Jedis , lettuce , Redisson

Spring,SpringBoot中有 一个RedisTemplate(StringRedisTemplate) ,处理和redis交互

6.1 配置Windows版本的redis

Redis-x64-3.2.100.rar 解压缩到一个 非中文 的目录

redis-server.exe:服务端, 启动后,不要关闭

redis-cli.exe:客户端, 访问redis中的数据

redisclient-win32.x86_64.2.0.jar : Redis图形界面客户端

执行方式: 在这个文件所在的目录, 执行 java -jar redisclient-win32.x86_64.2.0.jar

RedisTemplate 使用的 lettuce 客户端库

<!--redis起步依赖: 直接在项目中使用RedisTemplate(StringRedisTemplate)-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
data-redis使用的   lettuce 客户端库

在程序中使用RedisTemplate类的方法 操作redis数据, 实际就是调用的lettuce 客户端的中的方法


6.2 对比 StringRedisTemplate 和 RedisTemplate

StringRedisTemplate : 把k,v 都是作为String处理, 使用的是String的序列化 , 可读性好

RedisTemplate : 把k,v 经过了序列化存到redis。 k,v 是序列化的内容, 不能直接识别.

​ 默认使用的jdk序列化, 可以修改为前提的序列化

序列化:把对象转化为可传输的字节序列过程称为序列化。

反序列化:把字节序列还原为对象的过程称为反序列化。

为什么需要序列化

序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。

什么情况下需要序列化

通过上面我想你已经知道了凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。

本质上存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息。

序列化的方式

序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:

JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protofbuff、

Student( name=zs, age=20) ---- { “name”:“zs”, “age”:20 }

java的序列化: 把java对象转为byte[], 二进制数据

json序列化:json序列化功能将对象转换为 JSON 格式或从 JSON 格式转换对象。例如把一个Student对象转换为JSON字符串{“name”:“李四”, “age”:29} ),反序列化(将JSON字符串 {“name”:“李四”, “age”:29} 转换为Student对象)

设置key或者value的序列化方式

// 使用RedisTemplate ,在存取值之前,设置序列化
// 设置 key 使用String的序列化
redisTemplate.setKeySerializer( new StringRedisSerializer());

// 设置 value 的序列化
redisTemplate.setValueSerializer( new StringRedisSerializer());

redisTemplate.opsForValue().set(k,v);

第七章 SpringBoot集成Dubbo

7.1 看 SpringBoot继承Dubbo的文档

https://github.com/apache/dubbo-spring-boot-project/blob/master/README_CN.md

7.2 公共项目

独立的maven项目: 定义了接口和数据类

public class Student implements Serializable {
    private static final long serialVersionUID = 1901229007746699151L;

    private Integer id;
    private String name;
    private Integer age;
}

public interface StudentService {

    Student queryStudent(Integer id);
}

7.3 提供者

创建SpringBoot项目

1) pom.xml

<dependencies>

   <!--加入公共项目的gav-->
   <dependency>
      <groupId>com.bjpowernode</groupId>
      <artifactId>022-interface-api</artifactId>
      <version>1.0.0</version>
   </dependency>

   <!--dubbo依赖-->
   <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
      <version>2.7.8</version>
   </dependency>


   <!--zookeeper依赖-->
   <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-dependencies-zookeeper</artifactId>
      <version>2.7.8</version>
      <type>pom</type>
      <exclusions>
         <!-- 排除log4j依赖 -->
         <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
         </exclusion>
      </exclusions>
   </dependency>
</dependencies>

2)实现接口

/**
 * 使用dubbo中的注解暴露服务
 * @Component 可以不用加
 */
@DubboService(interfaceClass = StudentService.class,version = "1.0",timeout = 5000)
public class StudentServiceImpl implements StudentService {
    @Override
    public Student queryStudent(Integer id) {
        Student student  = new Student();
        if( 1001 == id){
            student.setId(1001);
            student.setName("------1001-张三");
            student.setAge(20);
        } else if(1002  == id){
            student.setId(1002);
            student.setName("#######1002-李四");
            student.setAge(22);
        }

        return student;
    }
}

3)application.properties

#配置服务名称 dubbo:application name="名称"
spring.application.name=studentservice-provider

#配置扫描的包, 扫描的@DubboService
dubbo.scan.base-packages=com.bjpowernode.service

#配置dubbo协议
#dubbo.protocol.name=dubbo
#dubbo.protocol.port=20881

#注册中心
dubbo.registry.address=zookeeper://localhost:2181

4)在启动类的上面

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {

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

7.4消费者

创建SpringBoot项目

1) pom.xml

<dependencies>

   <!--加入公共项目的gav-->
   <dependency>
      <groupId>com.bjpowernode</groupId>
      <artifactId>022-interface-api</artifactId>
      <version>1.0.0</version>
   </dependency>

   <!--dubbo依赖-->
   <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
      <version>2.7.8</version>
   </dependency>


   <!--zookeeper依赖-->
   <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-dependencies-zookeeper</artifactId>
      <version>2.7.8</version>
      <type>pom</type>
      <exclusions>
         <!-- 排除log4j依赖 -->
         <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
         </exclusion>
      </exclusions>
   </dependency>
</dependencies>
  1. 创建了Controller 或者 Service都可以
@RestController
public class DubboController {

    /**
     * 引用远程服务, 把创建好的代理对象,注入给studentService
     */
    //@DubboReference(interfaceClass = StudentService.class,version = "1.0")

    /**
     * 没有使用interfaceClass,默认的就是 引用类型的 数据类型
      */
    @DubboReference(version = "1.0")
    private StudentService studentService;

    @GetMapping("/query")
    public String queryStudent(Integer id){
        Student student   = studentService.queryStudent(id);
        return "调用远程接口,获取对象:"+student;
    }
}

3)application.properties

#指定服务名称
spring.application.name=consumer-application
#指定注册中心
dubbo.registry.address=zookeeper://localhost:2181

7.5 练习

使用的技术: SpringBoot ,Dubbo, Redis, MyBatis

Student表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GAPtXzD0-1647521439162)(D:\course\25-SpringBoot\笔记\images\image-20210119150418295.png)]

CREATE TABLE student (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) COLLATE utf8_bin DEFAULT NULL,
phone varchar(11) COLLATE utf8_bin DEFAULT NULL,
age int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

  1. 注册学生

​ phone必须唯一, 如果已经存在了手机号, 注册失败的。

​ int addStudent(Student student);

​ 返回值:int

​ 1: 注册成功

​ 2 : 手机号已经存在

​ name至少两个字符,

​ age 必须 大于 0

2) 查询学生,根据id查询,此学生。

​ 先到redis查询学生, 如果redis没有此学生,从数据库查询, 把查询到的学生放入到redis。

​ 后面再次查询这个学生应该从redis就能获取到。

​ Student queryStudent(Integer id);

  1. 使用Dubbo框架, addStudent, queryStudent 是有服务提供者实现的。

​ 消费者可以是一个Controller , 调用提供者的两个方法。 实现注册和查询。

4)页面使用html和ajax,jquery。

​ 在html页面中提供 form 注册学生, 提供文本框输入id,进行查询。

​ 注册和查询都使用ajax技术。

​ html,jquery.js都放到resources/static目录中

第八章 打包

8.1 打包war

1.创建了一个jsp应用

2.修改pom.xml

1)指定打包后的文件名称

<build>
   <!--打包后的文件名称-->
   <finalName>myboot</finalName>
</build>

2)指定jsp编译目录

<!--resources插件, 把jsp编译到指定的目录-->
<resources>
   <resource>
      <directory>src/main/webapp</directory>
      <targetPath>META-INF/resources</targetPath>
      <includes>
         <include>**/*.*</include>
      </includes>
   </resource>

   <!--使用了mybatis ,而且mapper文件放在src/main/java目录-->
   <resource>
      <directory>src/main/java</directory>
      <includes>
         <include>**/*.xml</include>
      </includes>
   </resource>

   <!--把src/main/resources下面的所有文件,都包含到classes目录-->
   <resource>
      <directory>src/main/resources</directory>
      <includes>
         <include>**/*.*</include>
      </includes>
   </resource>
</resources>

3)执行打包是war

<!--打包类型-->
<packaging>war</packaging>

4)主启动类继承SpringBootServletInitializer

/**
 * SpringBootServletInitializer: 继承这个类, 才能使用独立tomcat服务器
 */
@SpringBootApplication
public class JspApplication  extends SpringBootServletInitializer  {

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

   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
      return builder.sources(JspApplication.class);
   }
}

5)部署war

把war放到tomcat等服务器的发布目录中。 tomcat为例, myboot.war放到tomcat/webapps目录。

8.2 打包为jar

1.创建了一个包含了jsp的项目

2.修改pom.xml

​ 1) 指定打包后的文件名称

<build>
   <!--打包后的文件名称-->
   <finalName>myboot</finalName>
</build>
  1. 指定springboot-maven-plugin版本
<plugins>
   <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <!--打包jar, 有jsp文件时,必须指定maven-plugin插件的版本是 1.4.2.RELEASE-->
      <version>1.4.2.RELEASE</version>
   </plugin>
</plugins>

3)最后执行 maven clean package

​ 在target目录中,生成jar 文件, 例子是myboot.jar

​ 执行独立的springboot项目 在cmd中 java -jar myboot.jar

第九章 Thymeleaf 模板引擎

Thymeleaf: 是使用java开发的模板技术, 在服务器端运行。 把处理后的数据发送给浏览器。

​ 模板是作视图层工作的。 显示数据的。 Thymeleaf是基于Html语言。 Thymleaf语法是应用在

​ html标签中 。 SpringBoot框架集成Thymealeaf, 使用Thymeleaf代替jsp。

Thymeleaf 的官方网站:http://www.thymeleaf.org
Thymeleaf 官方手册:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

9.1 表达式

  1. 标准变量表达式

    语法: ${key}

    作用: 获取key对于的文本数据, key 是request作用域中的key , 使用request.setAttribute(), model.addAttribute()

    在页面中的 html标签中, 使用 th:text="${key}"

<div style="margin-left: 400px">
    <h3>标准变量表达式:  ${key}</h3>
    <p th:text="${site}">key不存在</p>
    <br/>
    <p>获取SysUser对象 属性值</p>
    <p th:text="${myuser.id}">id</p>
    <p th:text="${myuser.name}">姓名</p>
    <p th:text="${myuser.sex}">姓名:m男</p>
    <p th:text="${myuser.age}">年龄</p>
    <p th:text="${myuser.getName()}">获取姓名使用getXXX</p>
</div>
  1. 选择变量表达式( 星号变量表达式)

    语法: *{key}

    作用: 获取这个key对应的数据, *{key}需要和th:object 这个属性一起使用。

    目的是简单获取对象的属性值。

    <p>使用 *{} 获取SysUser的属性值</p>
    <div th:object="${myuser}">
        <p th:text="*{id}"></p>
        <p th:text="*{name}"></p>
        <p th:text="*{sex}"></p>
        <p th:text="*{age}"></p>
    
    </div>
    <p>使用*{}完成的表示 对象的属性值</p>
    <p th:text="*{myuser.name}" ></p>
    
  2. 链接表达式

    语法: @{url}

    作用: 表示链接, 可以

     <script src="..."> , <link href="..."> <a href=".."> ,<form action="..."> <img src="...">
    

9.2 Thymeleaf属性

属性是放在html元素中的,就是html元素的属性,加入了th前缀。 属性的作用不变。 加入上th, 属性的值由模板引擎处理了。 在属性可以使用变量表达式

例如:

<form action="/loginServlet" method="post"></form>

<form th:action="/loginServlet" th:method="${methodAttr}"></form>

9.3 each

each循环, 可以循环List,Array

语法:

在一个html标签中,使用th:each

<div th:each="集合循环成员,循环的状态变量:${key}">
    <p th:text="${集合循环成员}" ></p>
</div>

集合循环成员,循环的状态变量:两个名称都是自定义的。 “循环的状态变量”这个名称可以不定义,默认是"集合循环成员Stat"


each循环Map

在一个html标签中,使用th:each

<div th:each="集合循环成员,循环的状态变量:${key}">
    <p th:text="${集合循环成员.key}" ></p>
    <p th:text="${集合循环成员.value}" ></p>
</div>

集合循环成员,循环的状态变量:两个名称都是自定义的。 “循环的状态变量”这个名称可以不定义,默认是"集合循环成员Stat"

key:map集合中的key
value:map集合key对应的value值

9.4 th:if

“th:if” : 判断语句, 当条件为true, 显示html标签体内, 反之不显示 没有else语句

语法:
<div th:if=" 10 > 0 "> 显示文本内容 </div>

还有一个 th:unless 和 th:if相反的行为

语法:
<div th:unless=" 10 < 0 "> 当条件为false显示标签体内容 </div>

例子:if

<div style="margin-left: 400px">
        <h3> if 使用</h3>
        <p th:if="${sex=='m'}">性别是男</p>
        <p th:if="${isLogin}">已经登录系统</p>
        <p th:if="${age > 20}">年龄大于20</p>
        <!--""空字符是true-->
        <p th:if="${name}">name是“”</p>
        <!--null是false-->
        <p th:if="${isOld}"> isOld是null</p>
 </div>

例子: unless

 <div style="margin-left: 400px">
        <h3>unless: 判断条件为false,显示标签体内容</h3>
        <p th:unless="${sex=='f'}">性别是男的</p>
        <p th:unless="${isLogin}">登录系统</p>
        <p th:unless="${isOld}"> isOld是null </p>
 </div>

9.5 th:switch

th:switch 和 java中的swith一样的

语法:
<div th:switch="要比对的值">
    <p th:case="值1">
        结果1
    </p>
    <p th:case="值2">
        结果2
    </p>
    <p th:case="*">
        默认结果
    </p>
    以上的case只有一个语句执行
    
</div>

9.6 th:inline

  1. 内联text: 在html标签外,获取表达式的值

    语法:

    <p>显示姓名是:[[${key}]]</p>
    
     <div style="margin-left: 400px">
            <h3>内联 text, 使用内联表达式显示变量的值</h3>
            <div th:inline="text">
                <p>我是[[${name}]],年龄是[[${age}]]</p>
                我是<span th:text="${name}"></span>,年龄是<span th:text="${age}"></span>
            </div>
    
            <div>
                <p>使用内联text</p>
                <p>我是[[${name}]],性别是[[${sex}]]</p>
            </div>
    </div>
    
  2. 内联javascript

例子:
 <script type="text/javascript" th:inline="javascript">
         var myname = [[${name}]];
         var myage = [[${age}]];

         //alert("获取的模板中数据 "+ myname + ","+myage)

        function fun(){
            alert("单击事件,获取数据 "+ myname + ","+ [[${sex}]])
        }
    </script>

9.7 字面量

例子:

 <div style="margin-left: 400px">
       <h3>文本字面量: 使用单引号括起来的字符串</h3>
       <p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示</p>

       <h3>数字字面量</h3>
        <p th:if="${20>5}"> 20大于 5</p>

        <h3>boolean字面量</h3>
        <p th:if="${isLogin == true}">用户已经登录系统</p>

        <h3>null字面量</h3>
        <p th:if="${myuser != null}">有myuser数据</p>
    </div>

9.8 字符串连接

连接字符串有两种语法

1) 语法使用 单引号括起来字符串 , 使用 + 连接其他的 字符串或者表达式

  <p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示</p>

2)语法:使用双竖线, |字符串和表达式|

<p th:text="|我是${name},我所在城市${city|">
    显示数据
</p>

例子:

    <div style="margin-left: 400px">
       <h3>字符串连接方式1:使用单引号括起来的字符串</h3>
       <p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示</p>
        <br/>
        <br/>
        <h3>字符串连接方式2:|字符串和表达式|</h3>
        <p th:text="|我是${name},所在城市${city},其他人${myuser.name}|"></p>
    </div>

9.9 运算符

算术运 算: + , - - , * , / , %
关系比较 : > , < , >= , <= ( gt , lt , ge , le )
相等判断: == , != ( eq , ne )


<div style="margin-left: 400px">
        <h3>使用运算符</h3>
        <p th:text="${age > 10}">年龄大于 10 </p>
        <p th:text="${ 20 + 30 }">显示运算结果</p>
        <p th:if="${myuser == null}">myuser是null</p>
        <p th:if="${myuser eq null}">myuser是null</p>
        <p th:if="${myuser ne null}">myuser不是null</p>

        <p th:text="${isLogin == true ? '用户已经登录' : '用户需要登录'}"></p>
        <p th:text="${isLogin == true ? ( age > 10 ? '用户是大于10的' : '用户年龄比较小') : '用户需要登录'}"></p>

    </div>

三元运算符:
 表达式  ? true的结果 : false的结果

三元运算符可以嵌套

9.10 内置对象

文档地址:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#web-context-namespaces-for-requestsession-attributes-etc.

#request 表示 HttpServletRequest

#session 表示 HttpSession对象

session 表示Map对象的, 是#session的简单表示方式, 用来获取session中指定的key的值

​ #session.getAttribute(“loginname”) == session.loginname

这些是内置对象,可以在模板文件中直接使用。

例子:
 <div style="margin-left: 350px">
        <h3>内置对象#request,#session,session的使用</h3>
        <p>获取作用域中的数据</p>
        <p th:text="${#request.getAttribute('requestData')}"></p>
        <p th:text="${#session.getAttribute('sessionData')}"></p>
        <p th:text="${session.loginname}"></p>

        <br/>
        <br/>
        <h3>使用内置对象的方法</h3>
        getRequestURL=<span th:text="${#request.getRequestURL()}"></span><br/>
        getRequestURI=<span th:text="${#request.getRequestURI()}"></span><br/>
        getQueryString=<span th:text="${#request.getQueryString()}"></span><br/>
        getContextPath=<span th:text="${#request.getContextPath()}"></span><br/>
        getServerName=<span th:text="${#request.getServerName()}"></span><br/>
        getServerPort=<span th:text="${#request.getServerPort()}"></span><br/>
</div>

9.11 内置工具类

内置工具类型: Thymeleaf自己的一些类,提供对string, date ,集合的一些处理方法

#dates: 处理日器的工具类

#numbers:处理数字的

#lists: 处理list集合的

<div style="margin-left: 350px">
      <h3>日期类对象 #dates</h3>
      <p th:text="${#dates.format(mydate )}"></p>
      <p th:text="${#dates.format(mydate,'yyyy-MM-dd')}"></p>
      <p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}"></p>
      <p th:text="${#dates.year(mydate)}"></p>
      <p th:text="${#dates.month(mydate)}"></p>
      <p th:text="${#dates.monthName(mydate)}"></p>
      <p th:text="${#dates.createNow()}"></p>
      <br/>

      <h3>内置工具类#numbers,操作数字的</h3>
      <p th:text="${#numbers.formatCurrency(mynum)}"></p>
      <p th:text="${#numbers.formatDecimal(mynum,5,2)}"></p>

      <br/>
      <h3>内置工具类#strings,操作字符串</h3>
      <p th:text="${#strings.toUpperCase(mystr)}"></p>
      <p th:text="${#strings.indexOf(mystr,'power')}"></p>
      <p th:text="${#strings.substring(mystr,2,5)}"></p>
      <p th:text="${#strings.substring(mystr,2)}"></p>
      <p th:text="${#strings.concat(mystr,'---java开发的黄埔军校---')}"></p>
      <p th:text="${#strings.length(mystr)}"></p>
      <p th:text="${#strings.length('hello')}"></p>
      <p th:unless="${#strings.isEmpty(mystr)}"> mystring 不是 空字符串  </p>

      <br/>
      <h3>内置工具类#lists,操作list集合</h3>
      <p th:text="${#lists.size(mylist)}"></p>
      <p th:if="${#lists.contains(mylist,'a')}">有成员a</p>
      <p th:if="!${#lists.isEmpty(mylist)}"> list 集合有多个成员</p>

      <br/>
      <h3>处理null</h3>
      <p th:text="${zoo?.dog?.name}"></p>

  </div>

9.12 自定义模板

模板是内容复用, 定义一次,在其他的模板文件中多次使用。

模板使用:

1.定义模板

2.使用模板

模板定义语法:

th:fragment="模板自定义名称"

例如:
<div th:fragment="head">
    <p>
        动力节点-java开发
    </p>
    <p>
        www.bjpowernode.com
    </p>
</div>

引用模板语法:

1) ~{templatename :: selector}
   templatename:  文件名称
   selector: 自定义模板名称
2)templatename :: selector
   templatename:  文件名称
   selector: 自定义模板名称

对于使用模板:有包含模板(th:include), 插入模板(th:insert)

第十章 总结

10.1 注解

Spring + SpringMVC + SpringBoot

创建对象的:
@Controller: 放在类的上面,创建控制器对象,注入到容器中
@RestController: 放在类的上面,创建控制器对象,注入到容器中。
             作用:复合注解是@Controller , @ResponseBody, 使用这个注解类的,里面的控制器方法的返回值                   都是数据

@Service : 放在业务层的实现类上面,创建service对象,注入到容器
@Repository : 放在dao层的实现类上面,创建dao对象,放入到容器。 没有使用这个注解,是因为现在使用MyBatis框               架,  dao对象是MyBatis通过代理生成的。 不需要使用@Repository、 所以没有使用。
@Component:  放在类的上面,创建此类的对象,放入到容器中。 

赋值的:
@Value : 简单类型的赋值, 例如 在属性的上面使用@Value("李四") private String name
          还可以使用@Value,获取配置文件者的数据(properties或yml)。 
          @Value("${server.port}") private Integer port

@Autowired: 引用类型赋值自动注入的,支持byName, byType. 默认是byType 。 放在属性的上面,也可以放在构造             方法的上面。 推荐是放在构造方法的上面
@Qualifer:  给引用类型赋值,使用byName方式。   
            @Autowird, @Qualifer都是Spring框架提供的。

@Resource : 来自jdk中的定义, javax.annotation。 实现引用类型的自动注入, 支持byName, byType.
             默认是byName, 如果byName失败, 再使用byType注入。 在属性上面使用


其他:
@Configuration : 放在类的上面,表示这是个配置类,相当于xml配置文件

@Bean:放在方法的上面, 把方法的返回值对象,注入到spring容器中。

@ImportResource : 加载其他的xml配置文件, 把文件中的对象注入到spring容器中

@PropertySource : 读取其他的properties属性配置文件

@ComponentScan: 扫描器 ,指定包名,扫描注解的

@ResponseBody: 放在方法的上面,表示方法的返回值是数据, 不是视图
@RequestBody : 把请求体中的数据,读取出来, 转为java对象使用。

@ControllerAdvice:  控制器增强, 放在类的上面, 表示此类提供了方法,可以对controller增强功能。

@ExceptionHandler : 处理异常的,放在方法的上面

@Transcational :  处理事务的, 放在service实现类的public方法上面, 表示此方法有事务


SpringBoot中使用的注解
    
@SpringBootApplication : 放在启动类上面, 包含了@SpringBootConfiguration
                          @EnableAutoConfiguration@ComponentScan


    
MyBatis相关的注解

@Mapper : 放在类的上面 , 让MyBatis找到接口, 创建他的代理对象    
@MapperScan :放在主类的上面 , 指定扫描的包, 把这个包中的所有接口都创建代理对象。 对象注入到容器中
@Param : 放在dao接口的方法的形参前面, 作为命名参数使用的。
    
Dubbo注解
@DubboService: 在提供者端使用的,暴露服务的, 放在接口的实现类上面
@DubboReference:  在消费者端使用的, 引用远程服务, 放在属性上面使用。
@EnableDubbo : 放在主类上面, 表示当前引用启用Dubbo功能。
    
    
    
    
    


    


/p>





mystring 不是 空字符串

  <br/>
  <h3>内置工具类#lists,操作list集合</h3>
  <p th:text="${#lists.size(mylist)}"></p>
  <p th:if="${#lists.contains(mylist,'a')}">有成员a</p>
  <p th:if="!${#lists.isEmpty(mylist)}"> list 集合有多个成员</p>

  <br/>
  <h3>处理null</h3>
  <p th:text="${zoo?.dog?.name}"></p>
```

9.12 自定义模板

模板是内容复用, 定义一次,在其他的模板文件中多次使用。

模板使用:

1.定义模板

2.使用模板

模板定义语法:

th:fragment="模板自定义名称"

例如:
<div th:fragment="head">
    <p>
        动力节点-java开发
    </p>
    <p>
        www.bjpowernode.com
    </p>
</div>

引用模板语法:

1) ~{templatename :: selector}
   templatename:  文件名称
   selector: 自定义模板名称
2)templatename :: selector
   templatename:  文件名称
   selector: 自定义模板名称

对于使用模板:有包含模板(th:include), 插入模板(th:insert)

第十章 总结

10.1 注解

Spring + SpringMVC + SpringBoot

创建对象的:
@Controller: 放在类的上面,创建控制器对象,注入到容器中
@RestController: 放在类的上面,创建控制器对象,注入到容器中。
             作用:复合注解是@Controller , @ResponseBody, 使用这个注解类的,里面的控制器方法的返回值                   都是数据

@Service : 放在业务层的实现类上面,创建service对象,注入到容器
@Repository : 放在dao层的实现类上面,创建dao对象,放入到容器。 没有使用这个注解,是因为现在使用MyBatis框               架,  dao对象是MyBatis通过代理生成的。 不需要使用@Repository、 所以没有使用。
@Component:  放在类的上面,创建此类的对象,放入到容器中。 

赋值的:
@Value : 简单类型的赋值, 例如 在属性的上面使用@Value("李四") private String name
          还可以使用@Value,获取配置文件者的数据(properties或yml)。 
          @Value("${server.port}") private Integer port

@Autowired: 引用类型赋值自动注入的,支持byName, byType. 默认是byType 。 放在属性的上面,也可以放在构造             方法的上面。 推荐是放在构造方法的上面
@Qualifer:  给引用类型赋值,使用byName方式。   
            @Autowird, @Qualifer都是Spring框架提供的。

@Resource : 来自jdk中的定义, javax.annotation。 实现引用类型的自动注入, 支持byName, byType.
             默认是byName, 如果byName失败, 再使用byType注入。 在属性上面使用


其他:
@Configuration : 放在类的上面,表示这是个配置类,相当于xml配置文件

@Bean:放在方法的上面, 把方法的返回值对象,注入到spring容器中。

@ImportResource : 加载其他的xml配置文件, 把文件中的对象注入到spring容器中

@PropertySource : 读取其他的properties属性配置文件

@ComponentScan: 扫描器 ,指定包名,扫描注解的

@ResponseBody: 放在方法的上面,表示方法的返回值是数据, 不是视图
@RequestBody : 把请求体中的数据,读取出来, 转为java对象使用。

@ControllerAdvice:  控制器增强, 放在类的上面, 表示此类提供了方法,可以对controller增强功能。

@ExceptionHandler : 处理异常的,放在方法的上面

@Transcational :  处理事务的, 放在service实现类的public方法上面, 表示此方法有事务


SpringBoot中使用的注解
    
@SpringBootApplication : 放在启动类上面, 包含了@SpringBootConfiguration
                          @EnableAutoConfiguration@ComponentScan


    
MyBatis相关的注解

@Mapper : 放在类的上面 , 让MyBatis找到接口, 创建他的代理对象    
@MapperScan :放在主类的上面 , 指定扫描的包, 把这个包中的所有接口都创建代理对象。 对象注入到容器中
@Param : 放在dao接口的方法的形参前面, 作为命名参数使用的。
    
Dubbo注解
@DubboService: 在提供者端使用的,暴露服务的, 放在接口的实现类上面
@DubboReference:  在消费者端使用的, 引用远程服务, 放在属性上面使用。
@EnableDubbo : 放在主类上面, 表示当前引用启用Dubbo功能。
    
    
    
    
    


    


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第 1 章 入门 ................................................ 1 1.1 Spring 风云再起 ........................................ 1 1.1.1 重新认识 Spring ............................ 2 1.1.2 Spring Boot 精要 ........................... 3 1.1.3 Spring Boot 不是什么 ................... 6 1.2 Spring Boot 入门 ....................................... 6 1.2.1 安装 Spring Boot CLI .................... 7 1.2.2 使用 Spring Initializr 初始化 Spring Boot 项目 .......................... 10 1.3 小结 ......................................................... 18 第 2 章 开发第一个应用程序 .................... 19 2.1 运用 Spring Boot ..................................... 19 2.1.1 查看初始化的 Spring Boot 新项目 .......................................... 21 2.1.2 Spring Boot 项目构建过程 解析 .............................................. 24 2.2 使用起步依赖 .......................................... 27 2.2.1 指定基于功能的依赖 ................... 28 2.2.2 覆盖起步依赖引入的传递依赖 .... 29 2.3 使用自动配置 .......................................... 30 2.3.1 专注于应用程序功能 ................... 31 2.3.2 运行应用程序 .............................. 36 2.3.3 刚刚发生了什么 ........................... 38 2.4 小结 ......................................................... 41 第 3 章 自定义配置 .................................... 42 3.1 覆盖 Spring Boot 自动配置 ..................... 42 3.1.1 保护应用程序 .............................. 43 3.1.2 创建自定义的安全配置 ............... 44 3.1.3 掀开自动配置的神秘面纱 ........... 48 3.2 通过属性文件外置配置 ........................... 49 3.2.1 自动配置微调 .............................. 50 3.2.2 应用程序 Bean 的配置外置 ......... 55 3.2.3 使用 Profile 进行配置 .................. 59 3.3 定制应用程序错误页面 ........................... 62 3.4 小结 ......................................................... 64 第 4 章 测试 ............................................... 66 4.1 集成测试自动配置 .................................. 66 4.2 测试 Web 应用程序 ................................. 68 4.2.1 模拟 Spring MVC ........................ 69 4.2.2 测试 Web 安全 ............................. 72 4.3 测试运行中的应用程序 ........................... 74 4.3.1 用随机端口启动服务器 ............... 75 4.3.2 使用 Selenium 测试 HTML 页面 ............................................. 76 4.4 小结 ......................................................... 78 第 5 章 Groovy 与 Spring Boot CLI ......... 80 5.1 开发 Spring Boot CLI 应用程序 .............. 80 5.1.1 设置 CLI 项目 .............................. 81 5.1.2 通过 Groovy 消除代码噪声 ......... 81 5.1.3 发生了什么 .................................. 85 5.2 获取依赖 .................................................. 86 5.2.1 覆盖默认依赖版本 ....................... 87 5.2.2 添加依赖仓库 .............................. 88 5.3 用 CLI 运行测试 ...................................... 89 5.4 创建可部署的产物 .................................. 91 5.5 小结 ......................................................... 91 第 6 章 在 Spring Boot 中使用 Grails ...... 93 6.1 使用 GORM 进行数据持久化 ................. 93 6.2 使用 Groovy Server Pages 定义视图 ....... 98 6.3 结合 Spring Boot 与 Grails 3 ................. 100 6.3.1 创建新的 Grails 项目 ................. 100 6.3.2 定义领域模型 ............................ 103 6.3.3 开发 Grails 控制器 ..................... 104 6.3.4 创建视图 .................................... 105 6.4 小结 ....................................................... 107 第 7 章 深入 Actuator .............................. 108 7.1 揭秘 Actuator 的端点 ............................ 108 7.1.1 查看配置明细 ............................ 109 7.1.2 运行时度量 ................................ 115 7.1.3 关闭应用程序 ............................ 121 7.1.4 获取应用信息 ............................ 121 7.2 连接 Actuator 的远程 shell .................... 122 7.2.1 查看 autoconfig 报告 ........... 123 7.2.2 列出应用程序的 Bean ............... 124 7.2.3 查看应用程序的度量信息 ......... 124 7.2.4 调用 Actuator 端点 .................... 125 7.3 通过 JMX 监控应用程序 ....................... 126 7.4 定制 Actuator ......................................... 128 7.4.1 修改端点 ID ............................... 128 7.4.2 启用和禁用端点 ........................ 129 7.4.3 添加自定义度量信息 ................. 129 7.4.4 创建自定义跟踪仓库 ................. 132 7.4.5 插入自定义健康指示器 ............. 134 7.5 保护 Actuator 端点 ................................ 136 7.6 小结 ....................................................... 138 第 8 章 部署 Spring Boot 应用程序 ........ 139 8.1 衡量多种部署方式 ................................ 139 8.2 部署到应用服务器 ................................ 140 8.2.1 构建 WAR 文件 ......................... 141 8.2.2 创建生产 Profile ........................ 142 8.2.3 开启数据库迁移 ........................ 145 8.3 推上云端 ............................................... 150 8.3.1 部署到 Cloud Foundry ............... 150 8.3.2 部署到 Heroku ........................... 153 8.4 小结 ....................................................... 155 附录 A Spring Boot 开发者工具 .............. 157 附录 B Spring Boot 起步依赖 ................. 163 附录 C 配置属性 ...................................... 169 附录 D Spring Boot 依赖 ......................... 202

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值