SpringBoot2 笔记 ( 非常详细,快速上手使用,暂不涉及底层原理)

SpringBoot2 笔记目录


初次学习SpringBoot,底层原理听的迷迷糊糊。因此,目前没有写关于底层的原理,仅记录一些基本的使用,毕竟先学会使用,才有兴趣了解底层,不然一开始就学习了解底层,个人感觉十分枯燥乏味。


一:创建可直接运行的 SpringBoot 项目

1 创建项目:

使用 Spring Initializr 可以快速创建一个SpringBoot项目,且无需配置即可运行出一个简单的 Hello World
在这里插入图片描述

选中需要的 依赖工具等,此时选择了web (代表是一个web项目),thymeleaf (类似jsp,html),pom.xml 配置文件中会自动生成这些依赖配置(starter)

加入DevTools 在项目启动后进行代码修改后可以用Ctrl+F9进行编译(不用重新启动)

加入Lombok可以简化JavaBean和日志等开发,比如其中的Data注解可以为实体类中的属性生成getter、setter、toString等方法

在这里插入图片描述
在这里插入图片描述


2 创建一个Controller:

在这里插入图片描述


3 编写业务代码:

@RestController //此注解相当于  @Controller + @ResponseBody
public class testHelloWorldController {
    @GetMapping("/testHelloWorld") //相当于GET方式的 @RequestMapping
    public String testHelloWorld() {
        return "Hello World !!!";
    }
}

4 启动项目,并测试:

在这里插入图片描述


二:配置文件

1 配置文件类型:

resources 路径下有一个自动生成的 properties 配置文件,使用方式和以前相同
在这里插入图片描述

2 yaml:

这里使用 yaml 来作为 配置文件

yaml 的使用:

@Data
public class Person {
    private String userName;
    private Boolean boss;
    private Date birth;
    private Integer age;
    private Pet pet;
    private String[] interests;
    private List<String> animal;
    private Map<String, Object> score;
    private Set<Double> salarys;
    private Map<String, List<Pet>> allPets;
}

@Data
public class Pet {
    private String name;
    private Double weight;
}

使用yaml来表示:

# yaml表示以上对象
person:
  userName: zhangsan
  boss: false
  birth: 2019/12/12 20:12:33
  age: 18
  pet: 
    name: tomcat
    weight: 23.4
  interests: [篮球,游泳]
  animal: 
    - jerry
    - mario
  score:
    english: 
      first: 30
      second: 40
      third: 50
    math: [131,140,148]
    chinese: {first: 128,second: 136}
  salarys: [3999,4999.98,5999.99]
  allPets:
    sick:
      - {name: tom}
      - {name: jerry,weight: 47}
    health: [{name: mario,weight: 47}]

3 配置 yaml (测试:修改Tomcat 端口号)

默认端口号为8080
在这里插入图片描述
按照个人习惯修改端口号 (ps: 不要使用已占用的端口号):
在这里插入图片描述

重新启动项目,发现端口号已经变为8888
在这里插入图片描述


4 yaml中配置 视图解析器 前缀 后缀

controller返回字符串时自动拼接为 /xxx.html

spring:
  mvc:
    view:
      prefix: /  
      suffix: .html

三:Web开发

1 静态资源访问:

静态资源放在自动生成的static文件夹下

(也可以放在和static同级目录名称为 public 或 resources文件夹下;这几种方法不用配置静态资源的路径,如果放在其他目录需要配置访问路径)

在这里插入图片描述

在这里插入图片描述


2 index.html 欢迎页支持

index.html 放在 static目录下,访问项目时会默认访问该页面

放在 static目录下
在这里插入图片描述

测试:访问该项目时,默认访问 index.html 文件
在这里插入图片描述


3 自定义 Favicon

将 favicon.ico 放在static 目录下,可以更改网页图标

测试:(Ctrl + F5 强制刷新,若仍然不变,可重启 idea)
在这里插入图片描述


4 Rest 使用

和 SpringMVC 使用方式一样,但简化了配置

主要是delete 和 put 方式,和 springmvc 学习的相同,表单请求post,再写一个name 为_method的隐藏域value 注明时 delete 还是 put

① 编写 html(以 index.html 为例)

<!--   get     -->
<form method="get" action="/testRest">
    <input type="submit" value="测试GET">
</form>

<!--   post     -->
<form method="post" action="/testRest">
    <input type="hidden" name="_method" value="POST">
    <input type="submit" value="测试POST">
</form>

<!--   delete     -->
<form method="post" action="/testRest">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="测试DELETE">
</form>

<!--   put     -->
<form method="post" action="/testRest">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="测试PUT">
</form>

② 配置 过滤器

springmvc 中说过, delete和 put 是通过 过滤器来实现判断的
在这里插入图片描述

③ 编写 Controller

ps:

@GetMapping 可以表示 @RequestMapping(method=RequestMethod.GET)
@PostMapping 可以表示 @RequestMapping(method=RequestMethod.POST)
@RestController //此注解相当于  @Controller + @ResponseBody
public class TestRest {

    @RequestMapping(value = "/testRest",method = RequestMethod.GET)
    public String testGet() {
        return "GET";
    }

    @RequestMapping(value = "/testRest",method = RequestMethod.POST)
    public String testPost() {
        return "POST";
    }

    @RequestMapping(value = "/testRest",method = RequestMethod.DELETE)
    public String testDelete() {
        return "DELETE";
    }

    @RequestMapping(value = "/testRest",method = RequestMethod.PUT)
    public String testPut() {
        return "PUT";
    }

5 基本注解的使用

(1) @PathVariable 注解:


① 编写 Controller
@RestController
public class TestParamter {
    @GetMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") int id) {
        return "id值为: "+id;
    }
}
② 测试:

在这里插入图片描述


(2)@RequestHeader 注解:

① 编写 Controller:
@GetMapping("/testRequestHeader")
public String testReuqestHeader(@RequestHeader("User-Agent") String header) {
    return "UA为:" + header;
}
② 测试:

在这里插入图片描述

(3) @RequestParam 注解:

① 编写 html:
<form action="/testRequestParam">
    <input type="text" name="name">
    <input  type="submit" value="提交">
</form>
② 编写 Controller:
@GetMapping("/testRequestParam")
public String testRequestParam(@RequestParam("name") String name) {
    return name;
}
③ 测试:

输入 “zhangsan",然后提交
在这里插入图片描述

输出结果:
在这里插入图片描述

(4)@RequestBody 注解:

@RequestBody 只能有一个,必须为 Post 请求才能被接收 , @RequestParam 可以有多个)


① 编写 html:
<form action="/testRequestBody" method="post">
    用户名:<input name="username"><br>
    密码: <input name="password"><br>
    爱好: <input name="hobby"><br>
    <input  type="submit" value="提交">
</form>
② 编写Controller:
@PostMapping("/testRequestBody")
public Map testRequestBody(@RequestBody String content) {
     Map<String,Object> map = new HashMap<>();
     map.put("content",content);
     return map;
 }
③ 测试:

在这里插入图片描述


6 自定义对象参数

和 SpringMVC所学一样,可以自动类型转换与格式化,可以级联封装

(1)编写 实体类:

① Person 类:
@Data //lombok中的此注解:自动生成getter,setter,toString等
public class Person {
    private String name;
    private String pwd;
    private Pet pet;
}
② Pet 类:
@Data //lombok中的此注解:自动生成getter,setter,toString等
public class Pet {
    private String name;
    private String kind;
}

(2)编写 Html:

<form action="/test">
   用户名:<input name="name"> <br>
    密码:<input name="pwd"> <br>
    宠物名:<input name="pet.name"> <br>
    宠物种类:<input name="pet.kind"> <br>
    <input type="submit" value="提交">
</form>

(3) 编写Controller:

@RestController
public class TestParamter222 {
    @GetMapping("/test")
    public String test(Person person) {
        return "接收到的数据: " + person;
    }
}

(4) 测试:

输入:
在这里插入图片描述


结果:
在这里插入图片描述


7 模板引擎-Thymeleaf

(一开始创建项目时,选中的 tool,使用与 jsp 相似)
在这里插入图片描述


8 拦截器

(1) 编写一个拦截器实现 HandlerInterceptor
@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    @Override //目标方法执行前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        log.info("preHandle拦截的请求路径是{}",requestURI);
        log.info("放行!");
        return true;
    }

(2) 拦截器注册到容器中(实现webMvcConfigurer的addInterceptors)

指定拦截器规则(如果是拦截所有,静态资源也会被拦截)

@Configuration // 该类为配置类
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()) //拦截器注册到容器中
                .addPathPatterns("/**"); //拦截所有请求路径
    }
}
(3) 编写 Html :
<!-- 测试拦截器 -->
<form method="post" action="/testInterceptor">
    用户名:<input name="name"> <br>
    密码:<input name="pwd"> <br>
    宠物名:<input name="pet.name"> <br>
    宠物种类:<input name="pet.kind"> <br>
    <input type="submit" value="登录">
</form>

(4) 编写 Controller:
@Slf4j
@RestController
public class TestInterceptor {
    @PostMapping("/testInterceptor")
    public void testInterceptor(Person person, HttpSession session) {
        log.info("到达Controller");
    }
}

(5) 测试:

在这里插入图片描述
在这里插入图片描述


9 文件上传

① 编写 html:

(multiple:支持多文件上传)

<form action="/testFileUpload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" multiple><br> 
    <input type="submit" value="上传">
</form>

② 编写 Controller:

@Controller
public class TestFileUpload {
    @PostMapping("/testFileUpload")
    public String testFileUpload(@RequestPart("file") MultipartFile[] files) throws IOException {
        if(files.length > 0) { //有文件
            for (MultipartFile file : files) {
            	// 获取原文件名
                String originalFilename = file.getOriginalFilename();
                // 把该文件 放到该目录下
                file.transferTo(new File("C:/Users/ACER/Desktop/file/"+originalFilename));
            }
            return "success";
        }
        return "";
    }
}

③ 配置 上传文件的大小

单个文件大小最大1MB一次总上传文件大小最大为10MB

spring
	servlet:
	    multipart:
	      max-file-size: 1MB 
	      file-size-threshold: 10MB

④ 测试:

选中 符合配置的文件,然后上传,在目标文件下就可以看到文件已经传过来了


10 自定义异常

error 目录下,放入404.html500.html,当出现404异常时,会自动使用404.html。500异常同理。

(404.html 中 <img src="404.jpg">)

(500.html 中 <img src="500.png">)
在这里插入图片描述

(1) 测试 404 异常:

随便访问个不存在的路径:
在这里插入图片描述


(2) 测试 500 异常:

编写 一个会触发500异常的Controller

@Controller
public class TestError {
    @GetMapping("/testError")
    public void testError() {
        int i = 1/0;
    }
}

直接访问该 controller
在这里插入图片描述


11 Web原生组件注入 (Servlet、Filter)

(1) Servlet

① 指定扫描包:

在主程序上方写注解指定扫描包:

@ServletComponentScan("com.heitao.boot") //指明原生组件的位置

在这里插入图片描述

② 编写Servlet:
@WebServlet("/testServlet")  //指定处理的路径
public class MyServlet extends HttpServlet {

    // 重写doGet 和 doPost
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("this is MyServlet!!!!");
    }

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

在这里插入图片描述


(2) Filter

① 编写 MyFilter:
@Slf4j //日志: log.info() 可以自定义日志信息
@WebFilter({"/ttt/*"}) //指定过滤的路径
public class MyFilter extends HttpFilter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("MyFilter 工作");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("MyFilter 初始化");
    }

    @Override
    public void destroy() {
    }
}
② 创建 ttt 目录 测试过滤器:

在这里插入图片描述

③ 测试

在这里插入图片描述

在这里插入图片描述


四:数据访问

1 druid 数据源 (使用 starter)

(1) 官方 GitHub:

写的很清楚:官方 GitHub 链接


(2) 配置 pom.xml

① 引入 druid-spring-boot-starter
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.17</version>
</dependency>
② spring-boot-starter-jdbc
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
② mysql-connector-java
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>

(3) 配置示例:

(雷神笔记)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db_account
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

    druid:
      aop-patterns: com.atguigu.admin.*  #监控SpringBean
      filters: stat,wall     # 底层开启功能,stat(sql监控),wall(防火墙)

      stat-view-servlet:   # 配置监控页功能
        enabled: true
        login-username: admin
        login-password: admin
        resetEnable: false

      web-stat-filter:  # 监控web
        enabled: true
        urlPattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'


      filter:
        stat:    # 对上面filters里面的stat的详细配置
          slow-sql-millis: 1000
          logSlowSql: true
          enabled: true
        wall:
          enabled: true
          config:
            drop-table-allow: false

(4) 编写 Controller:

@RestController
public class TestDruid {

    @Autowired 
    JdbcTemplate jdbcTemplate;

    @GetMapping("/sql")
    public String sql() {
        Long aLong = jdbcTemplate.queryForObject("select count(*) from student", long.class);
        return "student中的数据条数: " + aLong;
    }
}

(5) 测试:

在这里插入图片描述


多刷新几次sql页面(看到次数为 6)
在这里插入图片描述


2 mybatis 数据源

(1) 注解方式:

① 在 pom.xml 中引入 mybatis 的 starter
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>

② 数据库 和 实体类

数据库:
在这里插入图片描述

实体类: Student

@Data //lombak工具中的此注解可以自动生成setter,getter,tostring等方法
public class Student {
    private int sno;
    private String sname;
    private int sage;
}

③ StudentMapper (相当于Dao层)
@Mapper
public interface StudentMapper {
    @Select("select * from student where sno = #{sno}")
    public Student findStudentById(int sno);
}

④ StudentService (Service层)

(测试,简单写写)

@Service
public class StudentService {
    @Autowired
    StudentMapper studentMapper; //可能有红色下划线,运行没有问题

    public Student findStudentById(int sno) {
        return studentMapper.findStudentById(sno);
    }
}

⑤ TestMybatis (Controller 控制层)
@Controller
public class TestMybatis {
    @Autowired
    StudentService studentService;

    @ResponseBody
    @GetMapping("/testMybatis")
    public Student testMybatis(int sno) {
        return studentService.findStudentById(sno);
    }
}

⑥ 测试:

在这里插入图片描述


(2) xml 方式:

和注解方式的不同之处主要是,xml方式不是直接使用注解写sql语句,而是通过xml,所以需要一些配置


(在注解方式的基础上,把 @Select 注解删除)

① 编写sql映射文件并绑定mapper接口

在这里插入图片描述

StudentMapper.xml 代码:

<?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 接口 -->
<mapper namespace="com.heitao.boot.Mapper.StudentMapper">

	<!-- 编写 sql映射 语句 -->
    <select id="findStudentById" resultType="com.heitao.boot.entity.Student">
        select * from student where sno = #{sno}
    </select>
</mapper>
② 在 yaml 配置文件中,指明 mapper配置文件 的位置
mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
③ 测试

在这里插入图片描述



五:单元测试

1 JUnit 5:

常用注解:

@Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试

@ParameterizedTest :表示方法是参数化测试,下方会有详细介绍

@RepeatedTest :表示方法可重复执行,下方会有详细介绍

@DisplayName :为测试类或者测试方法设置展示名称

@BeforeEach :表示在每个单元测试之前执行

@AfterEach :表示在每个单元测试之后执行

@BeforeAll :表示在所有单元测试之前执行

@AfterAll :表示在所有单元测试之后执行

@Tag :表示单元测试类别,类似于JUnit4中的@Categories

@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore

@Timeout :表示测试方法运行如果超过了指定时间将会返回错误

@ExtendWith :为测试类或测试方法提供扩展类引用

① 找到自动创建的 test

在这里插入图片描述


② 编写测试内容:
@SpringBootTest
class BootApplicationTests {

    @Test //测试1
    void contextLoads() {
        System.out.println("test1");
    }

    @Test //测试2
    void test2() {
        System.out.println("test2");
    }

    @BeforeAll //表示在所有单元测试之前执行
    static void beforeAll() {
        System.out.println("开始全部单元测试");
    }

    @AfterAll  //表示在所有单元测试之后执行
    static void afterAll() {
        System.out.println("全部单元测试完毕");
    }

    @BeforeEach //表示在每个单元测试之前执行
    void beforeEach() {
        System.out.println("开始进行一个单元测试");
    }

    @AfterEach //表示在每个单元测试之后执行
    void afterEach() {
        System.out.println("完成一个单元测试");
    }
}
③ 运行结果:

在这里插入图片描述
在这里插入图片描述


2 断言

(1) 简单断言

在这里插入图片描述

@Test
    public void test() {
        //判断两个对象或两个原始类型是否相等
        assertEquals(3,1+2);

        //判断两个对象或两个原始类型是否不相等
        assertNotEquals(3,2+2);

        Object obj1 = new Object();
        Object obj2 = new Object();
        //判断两个对象引用是否指向同一个对象
        assertSame(obj1,obj1);
        //判断两个对象引用是否指向不同的对象
        assertNotSame(obj1,obj2);

        //判断给定的布尔值是否为 true
        assertTrue(1<2);

        //判断给定的布尔值是否为 false
        assertFalse(1>2);

        //判断给定的对象引用是否为 null
        assertNull(null);

        //判断给定的对象引用是否不为 null
        assertNotNull(obj1);
    }

(2) 数组断言

@Test
    public void test() {
        int a[] = new int[]{1,2,3};
        int b[] = new int[]{1,2,3};
        //通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等
        assertArrayEquals(a,b);
    }

(3) 组合断言

@Test
    public void test() {
        //都成功,才成功
        assertAll(()->assertEquals(2,1+1),
                  ()->assertTrue(1 < 2));
    }

(4) 快速失败

@Test
    public void test() {
        if(1>2){
        //此时不失败,会打印 aaaaa,若条件符合执行fail,则不会打印aaaaa
            fail(); 
        } 
        System.out.println("aaaaa");
    }

3 参数化测试

@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型

@NullSource: 表示为参数化测试提供一个null的入参

@EnumSource: 表示为参数化测试提供一个枚举入参

@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参

@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)

(1) 测试 @ValueSource

@ParameterizedTest
    @ValueSource(strings = {"aaa","bbb","ccc"})
    public void test(String s) {
        System.out.println(s);
        assertNotEquals(s,"ddd");
    }

在这里插入图片描述


版权声明:本文为weixin_45260385原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。