SpringBoot2视频学习笔记

Author Avatar
hlmk 6月 03, 2018
  • 在其它设备中阅读本文章

工具的安装和使用

Eclipse安装SpringBoot相关插件

1.打开SpringBoot官网 https://spring.io/projects/spring-boot

enter description here

最近版本

enter description here

2.插件地址:https://spring.io/tools/sts/all

enter description here

点击下载最新版本插件

enter description here

3.打开eclipse ,点击菜单上的help—>Install New Software

enter description here

4.点击add按钮,点击Archive按钮,选择本地插件路径位置,如下图:

enter description here

5.选择所有的IDE项,选择不更新,点击下一步,如下图:

enter description here

6.安装完成后,重启eclipse

spring官网下载spring优化后的Eclipse

  1. 官网地址:https://spring.io/tools/sts/all/

enter description here

2.将解压后目录下的STS.exe上右键,—>发送到—>桌面快捷方式,如下图:

enter description here
使用方式和Eclipse一样
3.打开后,界面如下:

enter description here

创建Spring Boot项目

上面两种方式,创建Spring Boot项目的方式是一样的,具体步骤如下:

1.项目工程处,右键—>new—>Spring Starter Project

enter description here

如果new后面没有Spring Starter Project,执行如下步骤:
项目工程处,右键—>new—>Other,出现如下图弹框:
enter description here
Wizards下面输入spring后,Spring Starter Project,点击next

2.填写好配置后,点击next,如下图:

enter description here

3.选择Spring Boot 版本和项目类型,如下图,我选择了2.0.2和web

enter description here
点击finish

4.项目创建完成之后,目录机构如下图:

enter description here

RESTfull API简单项目的快速搭建

Eclipse快速打开项目文件所在位置

1.如图,菜单上右键点击Run—>External Tools—>External Tools Configurations…

enter description here

2.在Program上右键,选择New,如下图:

enter description here

3.配置参数,如下图:

enter description here

4.勾选Common下的External Tools,点击Apply后点击Run

enter description here

5.以后打开文件,只需要选中文件后,点击下图按钮即可,如图:

enter description here

RESTFull API简单项目搭建

eclipse装完STS插件和使用spring提供的eclipse搭建spring boot项目的方式是一样的,如果项目是spring boot的项目,建议使用STS,对spring的兼容很好。

基本SpringBoot项目示例

1.项目创建过程参考 创建Spring Boot项目 单元

2.创建HelloController,如下图:

enter description here

代码:

 package com.cht.demo1.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello spring boot ...";
    }

}

3.启动项目,如下图:

enter description here

4.访问项目,结果如下:

enter description here

SpringBoot热部署

添加spring-boot-devtools热部署依赖,快捷方式如下:

enter description here

或者手动在项目的pom.xml文件中添加如下依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

重启项目

这个作用就会修改了项目中的东西之后,springboot会自动将修改了的文件重新加载,不会重启tomcat和重新将项目的所有文件都加载一遍。

添加RESTFull支持

主要改变在@Controller注解替换为@RestController注解,@RestController注解是一个组合注解,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     * @since 4.0.1
     */
    @AliasFor(annotation = Controller.class)
    String value() default "";

}

可见,@RestController注解包含了@ResponseBody注解,所以,它下面的controller所有方法,返回的都是JSON数据,本demo中的应用如下:
1.创建User对象

package com.cht.demo1.bean;

import java.util.Date;

public class User {

    private int id;
    private String name;
    private Date date;


    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }




}

2.创建RestFullController,代码如下:

package com.cht.demo1.controller;

import java.util.Date;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cht.demo1.bean.User;

@RestController
@RequestMapping("/rest")
public class RestFullHelloController {

    @RequestMapping("/getUser/{id}/{name}")
    public User getUser(@PathVariable int id, @PathVariable String name) {
        User user = new User();
        user.setId(id);
        user.setName(name);
        user.setDate(new Date());
        return user;
    }

}

3.浏览器请求RestController下的接口,如下图:

enter description here

SpringBoot单元测试

1.在要创建单元测试的controller类上右键,如下图:

enter description here

2.配置测试类位置和类名等基本配置,如下图:

enter description here

3.选择要测试的方法,如下图:

enter description here

4.自动创建完成后的测试类如下:

package com.cht.demo1.controller;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


public class HelloControllerTest {

    @Test
    public void testHello() {
        fail("Not yet implemented");
    }

}

5.编写测试类,代码如下:

package com.cht.demo1.controller;

import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloControllerTest {

    private MockMvc mockMvc;

    @Before
    public void before() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
    }


    @Test
    public void testHello() throws Exception {
        RequestBuilder reBuilder = get("/hello");
        mockMvc.perform(reBuilder).andExpect(status().isOk()).andExpect(content().string("hello spring boot ..."));

    }

}

6.运行测试,如下图:

enter description here

绿色说明,测试通过,其他的controller测试类似。

springboot的打包

1.pom.xml中添加SpringBoot打包插件,代码如下:

            <!-- springboot 打包插件,作用就是将SpringBoot依赖的jar包导进打的jar包进去  -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

2.配置maven打包命令,如下图:

enter description here

enter description here
此maven命令的意思是先清除掉上次打的包,再重新打包

3.点击运行时,一般会报如下错误:

enter description here

4.配置eclipse的JDK,如下图:

enter description here
maven命令打包时,报错是应为项目使用的是jre,改成本地安装的jdk即可。

5.重新运行打包命令,打包结果如下:

enter description here

在target目录下会出现项目的jar文件,如下图:

enter description here

6.打开target所在目录之后,将cmd命令窗口切换到该目录,运行 java -jar 打包的文件名 运行打包的项目,如下图:

enter description here

浏览器可以正常请求访问,如下图:

enter description here

配置文件详解:properties与yaml

properties

配置文件的生效顺序,会对值进行覆盖:

1.@TestPropertySource注解
2.命令行参数
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.只有在random.*里包含的属性会产生一个 RandomValuePropertySource
6.在打包的jar外的应用程序配置文件(application.properties,包含YAML和profile变量)
7.在打包的jar内的应用程序配置文件(application.properties,包含YAML和profile变量)
8.在@Configuration类上的@PropertySource注解
9.默认属性(使用SpringApplication.setDefaultProperties指定)

配置随机值

roncoo.secret=${random.value}
roncoo.number=${random.int}
roncoo.bignumber=${random.long}
roncoo.number.less.than.ten=${random.int(10)}
roncoo.number.in.range=${random.int[1024,65536]}

读取使用注解:@Value(value=”${roncoo.secret}”)

注:出现黄点提示,是要提示配置元数据,可以不配置

属性占位符

当application.properties里的值被使用时,它们被存在的Environment过滤,所以你能够引用先前定义的值(比如,系统属性)。
roncoo.name=www.roncoo.com
roncoo.desc=${roncoo.name} is a domain name

Application属性文件,按优先级排序,位置高的将覆盖位置低的

1.当前目录下的一个/config子目录
2.当前目录
3.一个classpath下的/config包
4.classpath根路径(root)

这个列表是按照优先级排序的(列表中位置高的将覆盖位置低的)

配置应用端口和其他配置的介绍

配置参考文档位置:https://docs.spring.io/spring-boot/docs/2.0.2.RELEASE/reference/htmlsingle/#common-application-properties

端口配置:server.port=8090
时间格式化:spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
配置时区:spring.jackson.time-zone=Asia/wuhan

配置文件-多环境配置

一、多环境配置的好处
1.不同环境配置可以配置不同的参数
2.便于部署,提高效率,减少出错

二、properties多环境配置
1.配置激活选项 spring.profiles.active=dev
2.添加其他配置文件
application-dev.properties
application-prod.properties
application-test.properties
application.properties

YAML多环境配置
1.配置激活选项

spring:
    profiles:
        active: dev

2.在配置文件添加三个英文状态下的短横线即可区分

---
spring:
    profiles: dev

yaml

一、YAML是什么?
YAML是YAML Ain’t Markup Language递归缩写,是YAML不是标记语言的意思,读音“yamel”(或者“雅梅尔”)。YAML是便于人阅读基于unicode编码的各种语言的序列号标准。它的用途广泛,用于配置文件,日志文件,跨语言数据共享,对象持久化,复杂的数据结构。

二、yaml有什么特性,为什么使用yaml?
1、易于阅读;使用缩进,冒号(:),破折号(-)等人易于理解方式显示复杂的数据结构。

2、YAML数据在语言之间可以移植的。

3、符合敏捷语言的数据结构。

4、支持一次性操作。

5、具有表现力和可扩展性。

6、易于实现和使用

三、YAML与JSON
形同点:

1、YAML和JSON都是便于人阅读的数据交换格式。

不同点:

1、JSON设计主要在于简单和通用。YAML设计主要在于易于阅读和支持任何复杂的数据结构。

2、YAML可以视为JSON的超集,提供更易于阅读和复杂的信息模型。

3、每个JSON文件都是一个YAML文件,从JSON到YAML迁移是很容易的事情。

四、YAML与XML
YAML主要是数据序列号语言。XXML设计是对SGML的向后兼容。XML有设计约束,而YAML没有。

两种配置方式的比较

1.properties配置多环境,需要添加多个配置文件,YAML只需要一个配置文件
2.书写格式的差异,yaml相对比较简洁,优雅
3.yaml的缺点:不能通过@PropertySource注解加载。如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件

如何使用
java -jar demo-1.jar --spring.profiles.active=dev

日志配置logback和log4j2

支持日志框架:Java Util Logging, Log4j2 and Logback,默认使用logback
配置方式:默认配置文件配置和引用外部配置文件配置

默认配置文件配置(不建议使用:不够灵活,对log4j2等不够友好

//日志文件名,比如:roncoo.log,或者是/var/log/roncoo.log
logging.file=roncoo.log
//日志级别配置,比如:logging.level.org.springframework=DEBUG
logging.level.*=info
logging.level.org.springframework=DEBUG

引用外部配置文件

logback配置方式:

spring boot 默认加载 classpath:logback-spring.xml 或者 classpath:logback-spring.groovy

使用自定义配置文件,配置方式为:
logging.config=classpath:logback-roncoo.xml
注意:不要使用 logback 这个来命名,否则spring boot将不能完全实例化

1.1使用基于spring boot的配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

自定义配置

2.1 log4j配置
2.2.1 去除logback的依赖包,添加log4j2的依赖包

<exclusions>
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
</exclusions>

<!-- 使用log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

2.2.2 在classpath添加log4j2.xml或者log4j2-spring.xml(spring boot 默认加载)
2.3 自定义配置文件

比较

性能比较:log4j2和logback都优于log4j(不推荐使用)
配置方式:logback最简洁,spring boot默认,推荐使用

spring boot web应用开发

一、spring boot的web应用开发,是基于spring mvc

二、Spring boot在spring默认基础上,自动配置添加了以下特性:

  1. 包含了ContentNegotiatingViewResolver和BeanNameViewResolver beans。
  2. 对静态资源的支持,包括对WebJars的支持。
  3. 自动注册Converter,GenericConverter,Formatter beans。
  4. 对HttpMessageConverters的支持
  5. 自动注册MessageCodeResolver。
  6. 对静态index.html的支持。
  7. 对自定义Favicon的支持。
  8. 主动使用 ConfigurableWebBindingInitializer bean

三、模板引擎的选择
FreeMarker
Thymeleaf
Velocity(1.4版本之后弃用Spring Framework4.3版本之后弃用)
Groovy
Mustache
注:jsp应该尽量避免使用,原因如下:

  1. jsp只能打包为war格式,不支持jar格式,只能在标准的容器里面跑(tomcat、jetty都可以)
  2. 内嵌的Jetty目前不支持JSP
  3. Undertow不支持jsp
  4. jsp自定义错误页面不能覆盖spring boot默认的错误页面

springboot不同的版本下,模板引擎下可能引用了SpringBoot-start-web依赖,目前下面示例的2.0.2需要单独引用web依赖

四、FreeMarker Demo

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

五、Thymeleaf Demo

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

六、JSP Demo

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

模板引擎FreeMarker

创建一个FreeMarker模板引擎项目,具体步骤如下:
1.创建项目的时候,选择下图中的三项

enter description here

2.控制层代码

@Controller
@RequestMapping("/web")
public class WebController {

    private static final Logger logger = LoggerFactory.getLogger(WebController.class);


    @RequestMapping("/index")
    public String index(ModelMap map) {
        logger.info("这里是WebController...");
        map.put("title", "fremarker测试成功!");
        return "index";    //注意,不要在最前面加上/,linux下面会出错
    }

}
  1. 项目的静态文件和模板存放位置,如下图

enter description here
FreeMarker默认将静态文件存放在resources目录下的static目录,模板文件默认存放templates目录下

4.FreeMarker模板文件默认后缀名为.ftl
5.html文件示例代码

<!DOCTYPE html>
<html>
    <head lang="en">
        <title>Spring Boot Demo - FreeMarker</title>
        <link href="/css/index.css" ref="stylesheet"/>        
    </head>

    <body>
        <center>
            <img src="/images/logo.png"/>
            <h1 id="title">${title}</h1>
        </center>
    </body>

    <script type="text/javascript" src="/webjars/jquery/3.3.1-1/jquery.min.js"></script>

    <script>
        $(function(){
            $('#title').click(function(){
                alert("点击了");
            });
        });
    </script>

</html>

6.pom.xml文件中引入jquery,如下

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1-1</version>
        </dependency>

7.测试结果,如下图

enter description here

模板引擎Thymeleaf

此处只介绍模板引擎Thymeleaf项目的基本创建和使用

1.创建Thymeleaf项目,如下图

enter description here

2.Controller代码,如下

@Controller
@RequestMapping("/web")
public class WebController {

    private static final Logger logger = LoggerFactory.getLogger(WebController.class);


    @RequestMapping("/index")
    public String index(ModelMap map) {
        logger.info("这里是WebController...");
        map.put("title", "thymeleaf测试成功!");
        return "index";    //注意,不要在最前面加上/,linux下面会出错
    }

}

3.资源目录如下

enter description here

4.模板文件默认为html,示例index.html代码如下

<!DOCTYPE html>
<html>
    <head lang="en">
        <title>Spring Boot Demo - FreeMarker</title>
        <link href="/css/index.css" ref="stylesheet"/>        
    </head>

    <body>
        <center>
            <img src="/images/logo.png"/>
            <h1 id="title" th:text="${title}"></h1>
        </center>
    </body>

    <script type="text/javascript" src="/webjars/jquery/3.3.1-1/jquery.min.js"></script>

    <script>
        $(function(){
            $('#title').click(function(){
                alert("点击了...");
            });
        });
    </script>

</html>

5.引用jquery


        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1-1</version>
        </dependency>

6.测试

enter description here

模板殷勤jsp

spring boot是不建议使用jsp的,详情见上面的模板引擎选择
具体创建步骤如下
1.创建项目,如下图

enter description here

enter description here
创建完成后,项目结构如下

enter description here

ServletInitializer.java的作用和web.xml作用一样,是启动项目的入口,此适用于web3.0及其以上的规范,web2.0规范的还是需要web.xml作为web项目启动的入口

2.pom.xml中引入jsp相关jar包,如下图

        <!-- jsp解析 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- jstl支持 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

3.controller示例代码

@Controller
@RequestMapping("/web")
public class WebController {

    private static final Logger logger = LoggerFactory.getLogger(WebController.class);


    @RequestMapping("/index")
    public String index(ModelMap map) {
        logger.info("这里是WebController...");
        map.put("title", "jsp测试成功!");
        return "index";    //注意,不要在最前面加上/,linux下面会出错
    }

}

4.在webapp目录下,创建WEB-INF/templates目录,在新建的目录下,创建index.jsp,如下图

enter description here

5.application.properties做如下配置

spring.mvc.view.prefix=/WEB-INF/templates/
spring.mvc.view.suffix=.jsp

6.引入静态资源文件,如下图

enter description here

7.启动测试项目

enter description here

8.打成war包,本地启动

enter description here

enter description here

enter description here

错误处理

一、错误的处理

方法一:Spring Boot将所有的错误默认隐射到/error,实现ErrorController



@Controller
@RequestMapping("error")
public class ErrorTestController implements ErrorController{

    private static final Logger logger = LoggerFactory.getLogger(ErrorTestController.class);

    @Override
    public String getErrorPath() {
        logger.info("出错啦!进入自定义出错容器");
        return "error/error";
    }

    @RequestMapping
    public String error() {
        return getErrorPath();
    }

}

添加异常页面

enter description here

运行并试结果

enter description here

方法二:添加自定义的错误页面
2.1 html静态页面:在/resources/public/error/下定义
如添加404页面:resources/public/error/404.html页面,中文注意页面编码
2.2 模板引擎页面:在templates/error下定义
如添加5xx页面:templates/error/5xx.ftl

注:templates/error/ 这个的优先级比较 resources/pubilc/error/ 高

步骤如下

  1. 删除ErrorTestController.java
  2. html静态页面:在/resources/public/error/下定义
    如添加404页面:resources/public/error/404.html页面,中文注意页面编码
  3. 模板引擎页面:在templates/error下定义
    如添加5xx页面:templates/error/5xx.ftl

  4. 测试404,如下图

enter description here

测试error,如请求一下controller中的test

@Controller
@RequestMapping("/web")
public class WebController {

    private static final Logger logger = LoggerFactory.getLogger(WebController.class);


    @RequestMapping("/index")
    public String index(ModelMap map) {
        logger.info("这里是WebController...");
        map.put("title", "fremarker测试成功!");
        return "index";    //注意,不要在最前面加上/,linux下面会出错
    }


    @RequestMapping("/test")
    public String test(ModelMap map) {
        logger.info("这里是error test...");
        throw new RuntimeException("测试异常!");
    }

}

enter description here

方法三:使用注解@ControllerAdvice

  1. 创建异常处理类,示例代码如下
package com.cht.error.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义异常
 * @author 16694
 *
 */
@ControllerAdvice
public class BizException {

    private static final Logger logger = LoggerFactory.getLogger(BizException.class);

    /**
     * 统一异常处理
     * @param exception
     * @return
     */
    @ExceptionHandler({RuntimeException.class})
    @ResponseStatus(HttpStatus.OK)
    public ModelAndView processException(RuntimeException exception) {
        logger.info("自定义异常处理-RuntimeException...");
        ModelAndView mv = new ModelAndView();
        mv.addObject("roncooException",exception.getMessage());
        mv.setViewName("error/500");
        return mv;
    }

    /**
     * 统一异常处理
     * @param exception
     * @return
     */
    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.OK)
    public ModelAndView processException(Exception exception) {
        logger.info("自定义异常处理-Exception...");
        ModelAndView mv = new ModelAndView();
        mv.addObject("roncooException",exception.getMessage());
        mv.setViewName("error/500");
        return mv;
    } 
}

  1. 创建500.html页面,500.html页面示例代码
<!DOCTYPE html>
<html>
<head lang="en">
    <title>Spring Boot Demo - error</title>
</head>

<body>
    <h1>error-系统错误,请联系后台管理员</h1>
    错误信息:${roncooException}
</body>

</html>

  1. 启动 测试

enter description here

enter description here

Servlet、Filters、Listeners

一、Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能需要用到servlet、filter、listener等等

二、在spring boot中的三种实现方式
方法一、通过注册ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean获得控制

1.servlet

如下图,创建测试servlet

enter description here

代码如下

package com.cht.servletFilterListenter.util.servlet;

import java.io.IOException;

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


/**
 * 自定义servlet
 * @author 16694
 *
 */
public class CustomServlet extends HttpServlet{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet get method");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet post method");
        resp.getWriter().write("servlet test...");
    }

}

启动类中,注入servlet bean,代码如下

package com.cht.servletFilterListenter;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

import com.cht.servletFilterListenter.util.filter.CustomFileter;
import com.cht.servletFilterListenter.util.servlet.CustomServlet;

@SpringBootApplication
public class Demo62ServletFilterListernerApplication {

    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new CustomServlet(),"/roncoo");
    }



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

启动测试

enter description here

enter description here

2.filter
自定义filter代码如下

  package com.cht.servletFilterListenter.util.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 自定义filter
 * @author 16694
 *
 */
public class CustomFileter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init filter...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("doFilter filter...");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("destroy filter...");
    }



}

启动类注入filter bean代码

        @Bean
    public FilterRegistrationBean filterRegistrationBean() {
//        return new FilterRegistrationBean(new CustomFileter(),servletRegistrationBean());     //只拦截servletRegistrationBean
        return new FilterRegistrationBean(new CustomFileter());                        //拦截全部
    }

启动 测试

enter description here

enter description here

enter description here

3.listener
创建CustomListener,代码如下

package com.cht.servletFilterListenter.util.listerner;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 自定义 listener
 * @author 16694
 *
 */
public class CustomListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed...");
    }

}

启动类注册listener bean,代码如下

    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean() {
        return new ServletListenerRegistrationBean(new     CustomListener());
    }    

注册servlet、filter和listener的另一种方法

package com.cht.servletFilterListenter;

import java.util.EnumSet;

import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

import com.cht.servletFilterListenter.util.filter.CustomFileter;
import com.cht.servletFilterListenter.util.listerner.CustomListener;
import com.cht.servletFilterListenter.util.servlet.CustomServlet;

@SpringBootApplication
//public class Demo62ServletFilterListernerApplication{
public class Demo62ServletFilterListernerApplication implements ServletContextInitializer{

/*    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new CustomServlet(),"/roncoo");
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
//        return new FilterRegistrationBean(new CustomFileter(),servletRegistrationBean());     //只拦截servletRegistrationBean
        return new FilterRegistrationBean(new CustomFileter());                        //拦截全部
    }

    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean() {
        return new ServletListenerRegistrationBean(new     CustomListener());
    }    */



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


    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addServlet("customServlet", new CustomServlet()).addMapping("/roncoo");//此处路径少了“/”,启动会报错
        servletContext.addFilter("customFileter", new CustomFileter()).addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true,"customFileter");//拦截指定bean
//        servletContext.addFilter("customFileter", new CustomFileter()).addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true);//拦截所有
        servletContext.addListener(new CustomListener());
    }


}

主要代码如下

enter description here

方法三、在SpringBootApplication 上使用 @ServletComponentScan 注解后,直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,推荐第三种方法

启动类代码

package com.cht.servletFilterListenter;

import java.util.EnumSet;

import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

import com.cht.servletFilterListenter.util.filter.CustomFileter;
import com.cht.servletFilterListenter.util.listerner.CustomListener;
import com.cht.servletFilterListenter.util.servlet.CustomServlet;

@SpringBootApplication
@ServletComponentScan
//public class Demo62ServletFilterListernerApplication{
public class Demo62ServletFilterListernerApplication{
//public class Demo62ServletFilterListernerApplication implements ServletContextInitializer{

/*    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new CustomServlet(),"/roncoo");
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
//        return new FilterRegistrationBean(new CustomFileter(),servletRegistrationBean());     //只拦截servletRegistrationBean
        return new FilterRegistrationBean(new CustomFileter());                        //拦截全部
    }

    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean() {
        return new ServletListenerRegistrationBean(new     CustomListener());
    }    */



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


    /*@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addServlet("customServlet", new CustomServlet()).addMapping("/roncoo");//此处路径少了“/”,启动会报错
        servletContext.addFilter("customFileter", new CustomFileter()).addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true,"customFileter");//拦截指定bean
//        servletContext.addFilter("customFileter", new CustomFileter()).addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true);//拦截所有
        servletContext.addListener(new CustomListener());
    }*/


}

servlet代码

package com.cht.servletFilterListenter.util.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义servlet
 * @author 16694
 *
 */
@WebServlet(urlPatterns="/roncoo",name="customServlet")//此处路径少了“/”,启动会报错
public class CustomServlet extends HttpServlet{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet get method");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet post method");
        resp.getWriter().write("servlet test...");
    }

}

filter代码

package com.cht.servletFilterListenter.util.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**
 * 自定义filter
 * @author 16694
 *
 */
@WebFilter(urlPatterns="/*")//拦截全部
public class CustomFileter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init filter...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("doFilter filter...");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("destroy filter...");
    }



}

listener代码

package com.cht.servletFilterListenter.util.listerner;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * 自定义 listener
 * @author 16694
 *
 */
@WebListener
public class CustomListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed...");
    }

}


启动测试

enter description here

CORS支持

一、Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等
CORS和JSONP相比

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获取数据,比起JSONP有更好的错误处理。
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝多数现代浏览器都已经支持了CORS

浏览器支持情况
Chrom 3+
Pirefox 3.5+
Opera 12+
Safari 4+
Internet Explorer 8+

二、在spring MVC中可以配置全局规则,也可以使用@CrossOrigin注解进行细粒度的配置。

全局配置

@Configuration
public class CustomCorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                //http://localhost:8080下的api下的所有请求都允许跨域
                registry.addMapping("/api/**").allowedOrigins("http://localhost:8080");
            }
        };
    }
}

局部跨域配置
定义方法啊

@RestController
@RequestMapping("/api")
public class ApiController {

    @CrossOrigin(origins="http://localhost:8080")
    @RequestMapping("/get")
    public HashMap<String, Object> get(@RequestParam String name){
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", "跨域");
        map.put("name",name);
        return map;
    }

}

测试js

        $(function(){
            $('#title').click(function(){
                //alert("点击了");
                $.ajax({
                    url:"http://localhost:8081/api/get",
                    type:"POST",
                    data:{
                        name:"测试"
                    },
                    success:function(data,status,xhr){
                        console.log(data);
                        alert(data.name);
                    }
                });
            });
        });

测试效果

enter description here

文件上传

一、Spring Boot 默认使用spring MVC包装好的解析器进行上传

二、添加代码

js

<form method="POST" enctype="multipart/form-data" action="/file/upload">
    文件:<input type="file" name="roncooFile"/>
    <input type="submit" value="上传"/>
</form>

controller


@Controller
@RequestMapping("/file")
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);


    @RequestMapping("/upload")
    @ResponseBody()
    public String upload(@RequestParam("roncooFile") MultipartFile file) {
        if(file.isEmpty()) {
            return "文件为空";
        }

        //获取文件名
        String fileName = file.getOriginalFilename();
        logger.info("上传的文件名为:" + fileName);

        //获取文件后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));

        //文件上传路径
        String filePath = "d:/roncoo/education/";

        //解决中文问题,linux下中文路径,图片显示有问题
//        fileName = UUID.randomUUID() + suffixName;

        File dest = new File(filePath + fileName);

        //检测目录是否存在
        if(!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        try {
            //spring封装的方法上传
            file.transferTo(dest);
            return "上传成功!";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "上传失败!";
    }
}

测试

enter description here

三、配置

当上传的文件过大时,会报如下错误

Resolved exception caused by Handler execution: org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (20992233) exceeds the configured maximum (10485760)

spring boot 提供如下上传文件配置

# MULTIPART (MultipartProperties) 
# Whether to enable support of multipart uploads.默认支持上传
spring.servlet.multipart.enabled=true 
# Threshold after which files are written to disk. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.#支持文件写入磁盘
spring.servlet.multipart.file-size-threshold=0 
# Intermediate location of uploaded files.上传文件的临时目录(linux系统下配置成如:“/temp”,windows下配置成如:“D:/temp”)
spring.servlet.multipart.location= 
# Max file size. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.最大支持文件大小
spring.servlet.multipart.max-file-size=5MB 
# Max request size. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.最大支持请求大小
spring.servlet.multipart.max-request-size=10MB 
# Whether to resolve the multipart request lazily at the time of file or parameter access.
spring.servlet.multipart.resolve-lazily=false

SQL

使用关系型数据库-JdbcTemplate

一、配置数据源
嵌入式数据库的支持:Spring Boot 可以自动配置 H2,HSQL and Derby 数据库,不需要提供任何的链接URL,只需要加入相应的 jar 包,Spring Boot 可以自动发现装配

        <!-- 数据库 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

mysql 配置

#mysql配置
spring.datasource.url=jdbc:mysql://localhost/study
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

注:
1. 可以不指定driver-class-name,spring boot会自动识别url。
2. 数据连接池默认使用tomcat-jdbc

连接池配置:spring.datasource.tomcat.*

二、JdbcTemplate模板
//自动注册
@Autowired
private JdbcTemplate jdbcTemplate;

三、 脚本

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '注释',
  `user_name` varchar(30) NOT NULL COMMENT '用户名',
  `password` varchar(50) DEFAULT NULL COMMENT '密码',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `height` double DEFAULT NULL COMMENT '身高',
  `date` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '生日',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMNET='用户表';

四、实体类

/**
* 实体类
*/
public class RoncooUser(){
    private int id;
    private String name;
    private Date createTime;

    public int getId(){
        return id;
    }

    public void setId(int id){
        this.id = id;
    }

    public String getName(){
        return name;
    }

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

    public Date getCreateTime(){
        return createTime;
    }

}

使用关系型数据库-Spring-data-jpa

使用关系型数据库-事务处理

使用关系型数据库-h2嵌入式数据库的使用

使用NoSql数据库-redis

使用NoSql数据库-Mongodb

缓存

Ehcache

Redis

异步消息服务

JMS(ActiveMQ)

AMQP(RabbitMQ)

调用REST服务,如何使用代理

邮件

使用spring-session实现集群redis

远程调优

基于HTTP的监控

spring boot集成

集成Mybatis

集成Druid

集成Swagger

生产部署