SpringBoot-动力节点-王鹤

SpringBoot

  1. 为什么要使用 Spring Boot

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

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

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

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

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

1.1 第一章 Xml 和 JavaConfig

Spring 使用 Xml 作为容器配置文件, 在 3.0 以后加入了 JavaConfig. 使用 java 类做配置文件使用。

1.1.1 什么是 JavaConfig

JavaConfig: 是 Spring 提供的使用 java 类配置容器。 配置 Spring IOC 容器的纯 Java 方法。
优点:
1.可以使用面像对象的方式, 一个配置类可以继承配置类,可以重写方法
2.避免繁琐的 xml 配置

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

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

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

1.1.2 Xml 配置容器的方式

pom文件

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 编译插件 -->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- 插件的版本 -->
                <version>3.1</version>
                <!-- 编译级别 -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <!-- 编码格式 -->
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

创建数据类 Student

public class Student {
    String name;
    Integer age;
    String sex;

resources 目录下创建 Spring 的配置文件 applicationContext.xml

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

    <bean id="myCat" class="com.link.vo.Cat">
        <property name="name" value="tom猫"/>
        <property name="age" value="2" />
        <property name="cardId" value="uw532423422"/>
    </bean>
<!--   <context:property-placeholder location="classpath:config.properties" />-->
<!--    <context:component-scan base-package="com.link.vo" />-->
<!--    <import resource="classpath:beans.xml" />-->
</beans>

单元测试:

    /**
     * 使用xml作为容器配置文件
     */
    @Test
    public void test01(){
        String config="beans.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(config);
        Student myStudent = context.getBean("myStudent", Student.class);
        System.out.println("容器中的对象:"+myStudent);
    }

1.1.3 JavaConfig 配置容器的方式

JavaConfig 主要使用的注解
@Configuration:放在类的上面, 这个类相当于 xml 配置文件,可以在其中声明 bean
@Bean:放在方法的上面, 方法的返回值是对象类型, 这个对象注入到 spring ioc 容器

创建配置类(等同于 xml 配置文件)

/**
 * Configuration:表示当前类是作为配置文件使用的。 就是用来配置容器的
 *       位置:在类的上面
 *
 *  SpringConfig这个类就相当于beans.xml
 */
@Configuration
@ImportResource(value = {"classpath:applicationContext.xml","classpath:beans.xml"})
@PropertySource(value = "classpath:config.properties")
@ComponentScan(value = "com.link.vo")
public class SpringConfig {
    /**
     /**
     /**
     /**
     * 创建方法,方法的返回值是对象。 在方法的上面加入@Bean
     * 方法的返回值对象就注入到容器中。
     *
     * @Bean: 把对象注入到spring容器中。 作用相当于<bean>
     *     位置:方法的上面
     *     说明:@Bean,不指定对象的名称,默认是方法名是 id
     */
    @Bean
    public Student createStudent()
    {
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(20);
        s1.setSex("男");
        return s1;
    }
    /***
     * 指定对象在容器中的名称(指定<bean>的id属性)
     * @Bean的name属性,指定对象的名称(id)
     */
    @Bean(name="lisiStudent")
    public Student makeStudent(){
        Student s2 = new Student();
        s2.setName("李四");
        s2.setAge(25);
        s2.setSex("男");
        return s2;
    }
}

测试方法:

 /**
     * 使用JavaConfig
     */
    @Test
    public void test02(){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student student = ctx.getBean("createStudent", Student.class);
        System.out.println("使用JavaConfig创建的bean对象:"+student);
    }

    @Test
    public void test03(){
        ApplicationContext ctx  = new AnnotationConfigApplicationContext(SpringConfig.class);
        Student student = (Student) ctx.getBean("lisiStudent");
        System.out.println("使用JavaConfig创建的bean对象:"+student);
    }

1.1.4 @ImportResource

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

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

创建数据类:

public class Cat {

    private String cardId;
    private String name;
    private Integer age;

创建配置文件 applicationContext.xml

    <bean id="myCat" class="com.link.vo.Cat">
        <property name="name" value="tom猫"/>
        <property name="age" value="2" />
        <property name="cardId" value="uw532423422"/>
    </bean>

创建配置类:

/**
 * Configuration:表示当前类是作为配置文件使用的。 就是用来配置容器的
 *       位置:在类的上面
 *
 *  SpringConfig这个类就相当于beans.xml
 */
@Configuration
@ImportResource(value = {"classpath:applicationContext.xml","classpath:beans.xml"})
@PropertySource(value = "classpath:config.properties")
@ComponentScan(value = "com.link.vo")
public class SpringConfig {
    /**
     /**
     /**
     /**
     * 创建方法,方法的返回值是对象。 在方法的上面加入@Bean
     * 方法的返回值对象就注入到容器中。
     *
     * @Bean: 把对象注入到spring容器中。 作用相当于<bean>
     *     位置:方法的上面
     *     说明:@Bean,不指定对象的名称,默认是方法名是 id
     */
    @Bean
    public Student createStudent()
    {
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(20);
        s1.setSex("男");
        return s1;
    }
    /***
     * 指定对象在容器中的名称(指定<bean>的id属性)
     * @Bean的name属性,指定对象的名称(id)
     */
    @Bean(name="lisiStudent")
    public Student makeStudent(){
        Student s2 = new Student();
        s2.setName("李四");
        s2.setAge(25);
        s2.setSex("男");
        return s2;
    }
}

创建测试方法:

    @Test
    public void test04()
    {
        ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
        Cat myCat = ctx.getBean("myCat", Cat.class);
        System.out.println("容器中使用ImportResource从xml文件导入的对象:"+myCat);
        Student student = ctx.getBean("myStudent", Student.class);
        System.out.println("容器中使用ImportResource从xml文件导入的对象:"+student);
    }

1.1.5 @PropertyResource

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

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

1.在resources目录下,创建properties文件, 使用k=v的格式提供数据

tiger.name="大老虎"
tiger.age=3

创建数据类 Tiger

@Component("tiger")
public class Tiger {

    @Value("${tiger.name}")
    private String name;
    @Value("${tiger.age}")
    private Integer age;

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

2.在PropertyResource 指定properties文件的位置

/**
 * Configuration:表示当前类是作为配置文件使用的。 就是用来配置容器的
 *       位置:在类的上面
 *
 *  SpringConfig这个类就相当于beans.xml
 */
@Configuration
@ImportResource(value = {"classpath:applicationContext.xml","classpath:beans.xml"})
@PropertySource(value = "classpath:config.properties")
@ComponentScan(value = "com.link.vo")
public class SpringConfig {
    /**
     /**
     /**
     /**
     * 创建方法,方法的返回值是对象。 在方法的上面加入@Bean
     * 方法的返回值对象就注入到容器中。
     *
     * @Bean: 把对象注入到spring容器中。 作用相当于<bean>
     *     位置:方法的上面
     *     说明:@Bean,不指定对象的名称,默认是方法名是 id
     */
    @Bean
    public Student createStudent()
    {
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(20);
        s1.setSex("男");
        return s1;
    }
    /***
     * 指定对象在容器中的名称(指定<bean>的id属性)
     * @Bean的name属性,指定对象的名称(id)
     */
    @Bean(name="lisiStudent")
    public Student makeStudent(){
        Student s2 = new Student();
        s2.setName("李四");
        s2.setAge(25);
        s2.setSex("男");
        return s2;
    }
}

测试

    @Test
    public void test05(){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        Tiger tiger = (Tiger) ctx.getBean("tiger");
        System.out.println("tiger=="+tiger);
    }

注解的方式和xml的方式对比

@PropertySource(value = "classpath:config.properties")读取配置文件,
@Component("tiger") 使用注解的方式创建javabean
@ComponentScan(value = "com.link.vo") 扫描vo下所有使用注解方式创建的javabean
@ImportResource(value = {"classpath:applicationContext.xml","classpath:beans.xml"}) 导入其他xml文件
<context:property-placeholder location="classpath:config.properties" />
<context:component-scan base-package="com.link.vo" />
 <import resource="classpath:beans.xml" />

1.2 第二章 Spring Boot 入门

1.2.1 第一种方式:https://start.spring.io

第一种方式, 使用Spring提供的初始化器, 就是向导创建SpringBoot应用
使用 spring boot 提供的初始化器。 向导的方式,完成 spring boot 项目的创建: 使用方便。

1.2.1.1 创建项目步骤

step 1: 新建项目
在这里插入图片描述
step 2
zenzengka
step 3 选择依赖
在这里插入图片描述
step 4 : 最后创建项目,设置项目的目录位置
step 5: Spring Boot 项目目录结构
在这里插入图片描述

1.2.1.2 起步依赖

在这里插入图片描述

1.2.2 第二种方式,使用 springboot 提供的初始化器, 使用的国内的地址

国内地址: https://start.springboot.io
创建项目的步骤同上
在这里插入图片描述

1.2.3 第三种方式 使用 maven 向导创建项目

创建一个普通 maven 项目
在这里插入图片描述
在这里插入图片描述
点击 finish 创建,完成项目创建。
在这里插入图片描述
添加 Spring Boot 依赖

<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>
 </plugin>
 </plugins>
</build>

创建启动类:加入@SpringBootApplication 注解

package com.bjpowernode;
@SpringBootApplication
public class MySpringBootMain {
 public static void main(String[] args) {
 SpringApplication.run(MySpringBootMain.class,args);
 }
}
1.2.3.1 重要注解

@SpringBootApplication : @SpringBootApplication 是 一 个 复 合 注 解 , 是 由@SpringBootConfiguration,@EnableAutoConfiguration ,@ComponentScan 联合在一起组成的。
@SpringBootConfiguration : 就 是 @Configuration 这 个 注 解 的 功 能 , 使 用@SpringBootConfiguration 这个注解的类就是配置文件的作用。
@EnableAutoConfiguration:开启自动配置, 把一些对象加入到 spring 容器中。
@ComponentScan:组件扫描器, 扫描注解,根据注解的功能,创建 java bean,给属性赋值等等。组件扫描器默认扫描的是 @ComponentScan 注解所在的类, 类所在的包和子包。

1.2.4 Spring Boot 核心配置文件

Spring Boot 的核心配置文件用于配置 Spring Boot 程序,名字必须以 application 开始

配置文件名称: application

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

使用application.properties, application.yml

1.2.4.1 .properties 文件(默认采用该文件)

通过修改 application.properties 配置文件,在修改默认 tomcat 端口号及项目上下文件根键值对的 properties 属性文件配置方式

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

启动应用, 在浏览器访问 http://localhost:8082/myboot/

1.2.4.2 .yml 文件

yml 是一种 yaml 格式的配置文件,主要采用一定的空格、换行等格式排版进行配置。
yaml 是一种直观的能够被计算机识别的的数据序列化格式,容易被人类阅读,yaml 类似于 xml,但是语法比 xml 简洁很多,值与前面的冒号配置项必须要有一个空格, yml 缀也可以使用 yaml 后缀

server:
  port: 8083
  servlet:
    context-path: /myboot

注意 : 当两种格式配置文件同时存在 ,在 SpringBoot2.4 开始, 使用的是 yml 配置文件.修改配置名称都为 application。

当properties、yaml和yml三种文件路径相同时,三个文件中的配置信息都会生效,但是当三个文件中有配置信息冲突时,加载顺序是:yml > yaml > properties

yml的优先级会大于properties,所以如果同时存在这两种配置,因为properties是后加载的,所以此时yml就没有生效。由里向外加载,所以最外层的最后被加载,会覆盖里层的属性,最后被加载。所以最后生效的是properties 。

推荐使用 yml 格式配置文件

1.2.4.3 多环境配置

在实际开发的过程中,我们的项目会经历很多的阶段(开发->测试->上线),每个阶段的配置也会不同,例如:端口、上下文根、数据库等,那么这个时候为了方便在不同的环境之间切换,SpringBoot 提供了多环境配置,具体步骤如下

为每个环境创建一个配置文件,命名必须以 application-环境标识.properties|yml

在这里插入图片描述
application.properties

#激活使用哪个配置文件

#使用dev
#spring.profiles.active=dev

#使用test
spring.profiles.active=test

application-dev.yml

server:
  port: 8081
  servlet:
    context-path: /mydev

application-online.yml

server:
  port: 9002
  servlet:
    context-path: /myonline

application-test.yml

server:
  port: 9001
  servlet:
    context-path: /mytest
1.2.4.4 Spring Boot 自定义配置

SpringBoot 的核心配置文件中,除了使用内置的配置项之外,我们还可以在自定义配置,然后采用如下注解去读取配置的属性值

1.2.4.4.1 @Value 注解

@Value("${key}") , key 来自 application.properties(yml)

application.properties:添加两个自定义配置项 school.name 和 school.website。

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


#自定义k-v
school.name=linkacademy
school.website=www.linkacademy.com
school.address=成都市

site=www.baidu.com

读取配置文件数据
在这里插入图片描述

在这里插入图片描述

启动应用 Application , 访问浏览器

1.2.4.4.2 @ConfigurationProperties

@ConfigurationProperties: 把配置文件的数据映射为java对象。
属性:prefix 配置文件中的某些key的开头的内容。

@Component
@ConfigurationProperties(prefix = "school")
public class Academy {

    private String name;
    private String website;
    private String address;


    public String getName() {
        return name;
    }

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

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "Academy{" +
                "name='" + name + '\'' +
                ", website='" + website + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
@Controller
public class HelloController {

    @Value("${server.port}")
    private Integer port;
    @Value("${server.servlet.context-path}")
    private String contextPath;


    @Value("${site}")
    private String site;

    @Resource
    private Academy academy;

    @RequestMapping(value = "/data")
    @ResponseBody
    public String QueryDate()
    {
        return "prot:"+port+",contextPath:"+contextPath+",site:"+site+",site:"+site+",academy:"+academy;
    }

}

执行 Application , 访问浏览器查看数据

1.2.4.4.3 警告解决

在 SchoolInfo 类中使用了 ConfigurationProperties 注解,IDEA 会出现一个警告,不影响程序的执行
点击 open documentnation 跳转到网页,在网页中提示需要加一个依赖,我们将这个依赖拷贝,粘贴到 pom.xml 文件中

在这里插入图片描述

<!--解决使用@ConfigurationProperties 注解出现警告问题-->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 <optional>true</optional>
</dependency>
1.2.4.4.4 中文乱码

如果在 SpringBoot 核心配置文件中有中文信息,会出现乱码:
◼ 一般在配置文件中,不建议出现中文(注释除外)
◼ 如果有,可以先转化为 ASCII 码
在这里插入图片描述

1.2.5 Spring Boot 中使用 JSP

1.2.5.1 在 pom.xml 文件中配置以下依赖项

	<dependencies>

		<!--处理jsp依赖-->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<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>
1.2.5.2 在 pom.xml 的 build 标签中要配置以下信息

SpringBoot 要求 jsp 文件必须编译到指定的 META-INF/resources 目录下才能访问,否则访问不到。其实官方已经更建议使用模板技术(后面会讲模板技术)

	<!--指定jsp编译后的存放目录-->
		<resources>
			<resource>
				<!--jsp原来的目录-->
				<directory>src/main/webapp</directory>
				<!--指定编译后的存放目录-->
				<targetPath>META-INF/resources</targetPath>
				<!--指定处理的目录和文件-->
				<includes>
					<include>**/*.*</include>
				</includes>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
1.2.5.3 在 application.properties 文件配置 Spring MVC 的视图展示为

jsp,这里相当于 Spring MVC 的配置

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
1.2.5.4 在 com.bjpowernode.springboot.controller 包 下 创 建JspController 类,并编写代码
@Controller
public class JspController {

    /*public String doJsp(HttpServletRequest request){

        request.setAttribute("data","SpringBoot使用Jsp");
        //视图的逻辑名称
        return "index";
    }*/


    /**
     * ModelAndView:
     * @param model
     * @return
     */

    @RequestMapping("/myjsp")
    public String doJsp(Model model){

        //把数据放入到request作用域
        model.addAttribute("data","SpringBoot使用Jsp");
        //request.setAttribute("data","SpringBoot使用Jsp");

        //视图的逻辑名称
        return "index";
    }
}
1.2.5.5 在 src/main 下创建一个 webapp 目录,然后在该目录下新建index.jsp 页面

如果在webapp目录下右键,没有创建jsp的选项,可以在Project Structure中指定webapp
为 Web Resource Directory
在这里插入图片描述

1.2.5.6 在 jsp 中获取 Controller 传递过来的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp文件</title>
</head>
<body>
    <h3>使用jsp,显示Controller中的数据 ${data}</h3>
</body>
</html>

1.2.5.7 重新运行 Application,通过浏览器访问测试

在这里插入图片描述

1.2.6 Spring Boot 中使用 ApplicationContext

在 main 方法中 SpringApplication.run()方法获取返回的 Spring 容器对象,再获取业务 bean进行调用.
本质上是通过SpringApplication.run(Application.class, args); 返回值获取容器。
1.创建一个接口 UserService 和他的实现类

public interface UserService {

    void sayHello(String name);
}

2.创建启动类, main 方法中创建ConfigurableApplicationContext对象获取容器对象

@SpringBootApplication
public class Ch10SpringbootContainerApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext ctx= SpringApplication.run(Ch10SpringbootContainerApplication.class, args);

        UserService userService = ctx.getBean("userService", UserService.class);
        userService.sayHello("李四");

    }

}

1.2.7 CommandLineRunner 接口

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

public interface HelloService {

    String sayHello(String name);
}
@Service("helloService")
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "你好:"+name;
    }
}
@SpringBootApplication
public class Ch11SpringbootCommandlinerunnerApplication implements CommandLineRunner {
    @Resource
    private HelloServiceImpl helloService;

    public static void main(String[] args) {
        System.out.println("准备创建容器对象");
        //创建容器对象
        ConfigurableApplicationContext ctx = SpringApplication.run(Ch11SpringbootCommandlinerunnerApplication.class, args);
        System.out.println("容器对象创建之后");
    }

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

        String str  = helloService.sayHello("lisi");
        System.out.println("调用容器中的对象="+str);
        //可做自定义的操作,比如读取文件, 数据库等等
        System.out.println("在容器对象创建好,执行的方法");
    }


}

注意:@SpringBootApplication 启动类必须放在项目的根目录与所有包平级,一般在main方法内部通过执行

main方法启动类位于项目根目录的原因
@ComponentScan注解有个特性:如果不指定需要扫描的包或者需要注册的类,则默认是扫描该使用@ComponentScan注解的类所在的包以及子包,所以将使用了@SpringBootApplication注解的包含main方法的启动类放在项目根目录,则会扫描项目的所有包。
除了@ComponentScan注解之外,@EnableAutoConfiguration注解也是扫描使用了这个注解的类所在的包及其子包,故放在项目根目录,则可以扫描项目所有的包,对所有的类(具体为使用Spring容器管理的)进行检测,从而决定是否需要自动创建功能组件类的bean对象到spring的IOC容器中。

1.3 第三章 Spring Boot 和 web 组件

1.3.1 SpringBoot 中拦截器

1.3.1.1SpringMVC 使用拦截器

SpringMVC 使用拦截器
1)自定义拦截器类,实现 HandlerInterceptor 接口
2)注册拦截器类

//拦截器类:拦截用户的请求。
public class MyInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("111111-拦截器的MyInterceptor的preHandle()");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler, ModelAndView mv) throws Exception {
        System.out.println("111111-拦截器的MyInterceptor的postHandle()");
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        System.out.println("111111-拦截器的MyInterceptor的afterCompletion()");
    }
}
    <!--声明拦截器: 拦截器可以有0或多个
        在框架中保存多个拦截器是ArrayList,
        按照声明的先后顺序放入到ArrayList
    -->
    <mvc:interceptors>
        <!--声明第一个拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!--声明拦截器对象-->
            <bean class="com.link.handler.MyInterceptor" />
        </mvc:interceptor>
        <!--声明第二个拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.link.handler.MyInterceptor2" />
        </mvc:interceptor>
    </mvc:interceptors>
1.3.1.2Spring Boot 使用拦截器

1. 创建类实现 HandlerInterceptor 接口

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        System.out.println("执行了LoginInterceptor的preHandle");
        return true;
    }
}

2. 注册拦截器对象

@Configuration
public class MyAppConfig implements WebMvcConfigurer {

    //添加拦截器对象, 注入到容器中
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

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

        //指定拦截的请求uri地址
        String path []= {"/user/**"};
        //指定不拦截的地址
        String excludePath  [] = {"/user/login"};
        registry.addInterceptor(interceptor)
                .addPathPatterns(path)
                .excludePathPatterns(excludePath);

    }

}

3. 创建测试使用的 Controller

@Controller
public class BootController {

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

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

4. 主启动类

5. 启动主类, 运行浏览器
访问 user/account , user/login 观察拦截的输出语句

在这里插入图片描述

1.3.2 Spring Boot 中使用 Servlet

ServletRegistrationBean 用来做在 servlet 3.0+容器中注册 servlet 的功能,但更具有SpringBean 友好性。

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();
    }
}

2.注册 Servlet

@Configuration
public class WebApplictionConfig{
    //定义方法, 注册Servlet对象
    @Bean
    public ServletRegistrationBean servletRegistrationBean()
    {
        //第一种初始化方式
        ServletRegistrationBean bean = new ServletRegistrationBean(new MyServlet(),"/login","/test");
        //第二种初始化方式
//        ServletRegistrationBean bean = new ServletRegistrationBean();
//        bean.setServlet(new MyServlet());
//        bean.addUrlMappings("/login","/test");
        return bean;
    }
}

3.主启动类
4.启动主类,在浏览器中访问 loginServlet

在这里插入图片描述

在这里插入图片描述

1.3.3 Spring Boot 中使用 Filter

FilterRegistrationBean 用来注册 Filter 对象
实现步骤:
1.创建 Filter 对象

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行了MyFilter,doFilter ");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

2.注册 Filter

@Configuration
public class WebApplicationConfig {
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean bean=new FilterRegistrationBean();
        bean.setFilter(new MyFilter());
        bean.addUrlPatterns("/user/*");
        return bean;
    }

}

3.创建 Controller

@Controller
public class CustomFilterController {

    @RequestMapping("/user/account")
    @ResponseBody
    public String userAccount(){
        return "user/account";
    }


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


}

4.启动应用, 在浏览器访问 user/account, /query 查看浏览器运行结果

在这里插入图片描述
/query 则不会经过过滤器

1.3.4 字符集过滤器的应用

实现步骤:
1.创建 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 {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("===在Servlet输出中文,默认编码ISO-8859-1===");
        out.flush();
        out.close();
    }
}

2)注册 Servlet 和 Filter

@Configuration
public class WebSystemConfig{
    //注册servlet
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        ServletRegistrationBean bean=new ServletRegistrationBean(new MyServlet(),"/myservlet");
        return bean;

    }

    //注册filter
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        //使用框架中的过滤器类
        CharacterEncodingFilter filter=new CharacterEncodingFilter();
        //指定使用的编码方式
        filter.setEncoding("utf-8");
        //指定request response都使用encoding中的值
        filter.setForceEncoding(true);
        bean.setFilter(filter);
        //指定 过滤的url地址
        bean.addUrlPatterns("/*");
        return bean;

    }
}

3.在 application.properties , 禁用 Spring Boot 中默认启用的过滤器

server.servlet.encoding.enabled=false

4.启动主类,运行浏览器

1.3.5 在 application.properties 文件中设置过滤器

Spring Boot 项目默认启用了 CharacterEncodingFilter, 设置他的属性就可以

#设置 spring boot 中 CharacterEncodingFitler 的属性值
server.servlet.encoding.enabled=true 
server.servlet.encoding.charset=utf-8
#强制 request, response 使用 charset 他的值 utf-8
server.servlet.encoding.force=true

1.3.6过滤器和拦截器的整合

在这里插入图片描述

1.创建拦截器 ,注意需要使用@Component 或者在注册拦截器import拦截器的包 最好都加上

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        System.out.println("执行了LoginInterceptor的preHandle");
        return true;
    }
}

2.注册拦截器

@Configuration
public class MyAppConfig implements WebMvcConfigurer {

    //添加拦截器对象, 注入到容器中
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

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

        //指定拦截的请求uri地址
        String path []= {"/user/**"};
        //指定不拦截的地址
        String excludePath  [] = {"/user/login"};
        registry.addInterceptor(interceptor)
                .addPathPatterns(path)
                .excludePathPatterns(excludePath);

    }

}

3.注册过滤器 需要@Import(MyAppConfig.class) 需要import其他javaconfig

@Configuration
@Import(MyAppConfig.class)
public class WebSystemConfig{
    //注册servlet
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        ServletRegistrationBean bean=new ServletRegistrationBean(new MyServlet(),"/myservlet");
        return bean;

    }

    //注册filter
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        //使用框架中的过滤器类
        CharacterEncodingFilter filter=new CharacterEncodingFilter();
        //指定使用的编码方式
        filter.setEncoding("utf-8");
        //指定request response都使用encoding中的值
        filter.setForceEncoding(true);
        bean.setFilter(filter);
        //指定 过滤的url地址
        //bean.addUrlPatterns("/*");
        bean.addUrlPatterns("/user");
        return bean;

    }
}

1.4 第四章 ORM 操作 MySQL

讲解 MyBatis 框架,读写 MySQL 数据。通过 SpringBoot +MyBatis 实现对数据库学生表的查询操作。
创建数据库:数据库 springdb,指定数据库字符编码为 utf-8

CREATE TABLE `student` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(256) DEFAULT NULL,
  `age` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
 
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO student(`name`,`age`)
VALUES("小红",23),("小白",24),("张三",28),("李四",34)

1.4.1 创建 Spring Boot 项目

pom.xml

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </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>
            </plugin>
        </plugins>
    </build>

加入 resources 插件

<resources>
 <resource>
 <directory>src/main/java</directory>
 <includes>
 <include>**/*.xml</include>
 </includes>
 </resource>
</resources>

配置数据源:application.properties

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

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456


创建数实体 bean, dao 接口,mapper 文件
在这里插入图片描述
实体类

public class Student {
    
    private Integer id;
    private String name;
    private Integer age;

创建 Dao 接口

/**
 * @Mapper: 找到接口和他的 xml 文件
 * 位置:在接口的上面
 */
@Mapper
public interface StudentMapper {

    Student selectStudentById(@Param("stuid") Integer id);

}

mapper 文件:

<?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.link.dao.StudentMapper">

    <select id="selectStudentById" resultType="com.link.domain.Student">
        select id name age from student where id=#{stuid}
    </select>

</mapper>

service 接口

public interface StudentService {
    Student queryStudent(Integer id);
}

service 接口实现类

public class StudentServiceImpl implements StudentService {

    @Resource
    private StudentMapper studentDao;

    @Override
    public Student queryStudent(Integer id) {
        Student student = studentDao.selectStudentById(id);
        return student;
    }
}

controller 类

@Controller
public class StudentController {
    @Resource
    private StudentService studentService;
    @RequestMapping("/query")
    @ResponseBody
    public String queryStudent(Integer id)
    {
        Student student=studentService.queryStudent(id);
        return "查询的结果id是"+id+",学生:"+student.toString();
    }
}

启动 Application 类, 浏览器访问 http://localhost:9090/myboot/query

发现无法连接数据库
报错:

 Failed to obtain JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: 

是mysql-connecter-java版本太高,自己安装的mysql数据库版本低的问题,把mysql的jar包降低到适合自己mysql数据库的版本就好了
在这里插入图片描述
降低mysql-connector-java这个jar包的版本号,重新启动项目就可以正常访问了。

在这里插入图片描述

1.4.2 @MapperScan

在 Dao 接口上面加入@Mapper,需要在每个接口都加入注解。当 Dao 接口多的时候不方便。

可以使用如下的方式解决。
主类上添加注解包扫描:@MapperScan(“com.link.dao”)

/**
* @MapperScan: 扫描所有的 mybatis 的 dao 接口
* 位置:在主类的上面
* 属性:basePackages:指定 dao 接口的所在的包名。
* dao 接口和 mapper 文件依然在同一目录
*/
@SpringBootApplication
@MapperScan(basePackages = "com.link.dao")
public class MyBatisApplication2 {
 public static void main(String[] args) {
 SpringApplication.run(MyBatisApplication2.class,args);
 }
}

1.4.3 mapper 文件和 java 代码分开管理

这种方式比较推荐,mapper 文件放在 resources 目录下, java 代码放在 src/main/java。

在 resources 创建自定义目录,例如 mapper, 存放 xml 文件
在这里插入图片描述
在 application.properties 配置文件中指定映射文件的位置,这个配置只有接口和映射文件不在同一个包的情况下,才需要指定。

 #指定 mybatis 的配置, 相当于 mybatis 主配置文件的作用
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

1.4.4 事务支持

Spring Boot 使用事务非常简单,底层依然采用的是 Spring 本身提供的事务管理
在入口类中使用注解 @EnableTransactionManagement 开启事务支持
在访问数据库的 Service 方法上添加注解 @Transactional 即可

通过 SpringBoot +MyBatis 实现对数据库学生表的更新操作,在 service 层的方法中构建异常,查看事务是否生效。

@Service
public class StudentServiceImpl implements StudentService {
    @Resource
    private StudentMapper studentMapper;
    /**
     * @Transactional: 表示方法的有事务支持
     *       默认:使用库的隔离级别, REQUIRED 传播行为; 超时时间  -1
     *       抛出运行时异常,回滚事务
     */
    @Override
    @Transactional
    public int addStudent(Student student) {
        System.out.println("业务方法addStudent");
        int rows = studentMapper.insert(student);
        System.out.println("执行SQL语句");
        //抛出运行时异常,目的是回滚事物
        //int num = 5/0;
        return rows;
    }
}

在 Application 主类上,@EnableTransactionManagement 开启事务支持
@EnableTransactionManagement 可选,但是@Service 必须添加事务才生效

@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = "com.link.dao")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值