• SpringBoot终极讲义第一章笔记


    01.Spring Boot简介

    1.Spring的本质和作用

    spring的本质就是一个"容器",它负责创建并管理容器中的对象(组件,也称为Bean),并管理组件之间的依赖关系(何为依赖关系:A组件需要调用B组件方法,称为A依赖于B)

    因此学习Spring最常用的两个注解:

    @Component:将被修饰的类变成容器中的组件

            @Controller  @Service  @Repository本质都是@Component只不过更形象的表示哪个层级

            控制层,业务层,持久层.表示清楚而已

    @AutoWired:完成依赖注入

    2.javaEE和Spring

    3.java后端开发涉及的技术

    MVC层:Spring WebFlux,Spring MVC,Struts2等

    安全领域:Spring Security,Shiro等

    消息组件:ActiveMQ,RabbitMQ,Kafka等

    缓存:JCache,EhCache,Hazelcast,Redis等 

    持久层框架:JPA,Mybatis,JOOQ,R2DBC等

    分布式:Zookeeper,Dubbo等.

    NOSQL存储:Redsi,MongoDB,Neo4J,Cassandra,Geodo,CouchBase等

    全文检索引擎:Lucene,Solr,Elastichsearch等

    数据库存储:Mysql,PostgreSQL,Oracle等

    Web服务器:Tomcat,Jetty,Undertow等

    4.Spring与SpringBoot

    SpringBoot依然以Spring为核心,Spring的缺点是配置过多

    SpringBoot为绝大部分第三方框架的快速整合提供了自动配置

    针对各种框架提供了对应的Starter,只要添加该Starter即可完成第三方框架的自动整合

    SpringBoot整合了绝大对数常用的第三方框架

    5.SrpingBoot能做什么和不能做什么

    内嵌Tomcat,Jetty等服务器,因此SpringBoot 应用无需部署到其他服务器

    SpringBoot应用可做成独立的java应用程序--不需要是web应用

    意味着可以通过"java 主类"命令来运行应用.

    提供产品级监控功能(Spring Actuator),如运行状况检查和外部化配置等

    不要夸大SpringBoot的功能,SpringBoot直译就是Spring启动 

    它主要功能就是为Spring及第三方框架的快速启动提供了自动配置

    -----------------------------------------------------------------------------------------------------------------

    02.SpringBoot的项目结构

    创建时引入的依赖

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    

    03.控制器访问

    当访问localhost:8080/index时候无法访问,原因是这里是返回视图

    04.SpringBoot整合Thymeleaf作为视图模板技术

    引入Thymeleaf依赖

    
    
        org.springframework.boot
        spring-boot-starter-thymeleaf
    

    SpringBoot支持Webjar技术

    webjars:用于将各种前端资源(JS/CSS等打成jar包)

    引入bootstarp依赖:

    
    
        org.webjars
        bootstrap
        4.6.0
    

    Thymeleaf模板页面要放在resources/templates下

    在resources/templates/hello.html

    
    
    
    
        
        欢迎页面
        
        
    
    
    
    提示信息

    访问localhost:8080/index  视图转发到hello.html

    05.SpringBoot启动类作用

    06.运行及打包SpringBoot应用

    启动该项目

    第一种方式:进入项目的pom.xml所在路径 执行    mvn spring-boot:run

    CTRL+C  退出

    第二种方式:将SpringBoot应用打包

    打包有可能出错,如果是test问题

    进入target目录    java -jar xxx.jar   或者 java -jar xxx.jar &

    java -jar xxx.jar 是在当前窗口运行    java -jar xxx.jar & 是在后台运行

    IDEA的Terminal窗口:运行mvn spring-boot:run

    CTRL+C     Y结束

    双击CTRL键盘 回车

    这些真无聊  还可以

    还可以这样  这是闲的

    07.整合Thymeleaf添加service及dao

    为了项目看起来不那么乱,有迭代效果,复制一份

    templates下的文件不能直接访问,用控制器转发

    添加持久层依赖,这里用Spring Data JPA

    
    
        mysql
        mysql-connector-java
        runtime
    
    
    
    
        org.springframework.boot
        spring-boot-starter-data-jpa
    

    建库 

    Spring data jpa会自动帮你根据实体类创建表

    在application.properties配置

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://xxxx:3306/jpatest?serverTimezone=Asia/Shanghai
    spring.datasource.username=xxxx
    spring.datasource.password=xxxx
    
    #指定显示SQL语句
    spring.jpa.show-sql=true
    #指定根据尸体自动建表
    spring.jpa.generate-ddl=true

    实体类

    1. package com.example.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import lombok.experimental.Accessors;
    6. import javax.persistence.*;
    7. /**
    8. * @author hrui
    9. * @date 2023/10/1 2:12
    10. */
    11. @Data
    12. @NoArgsConstructor
    13. @AllArgsConstructor
    14. @Accessors(chain = true)
    15. @Entity
    16. @Table(name="book_inf")
    17. public class Book {
    18. @Id
    19. @Column(name="book_id")
    20. @GeneratedValue(strategy = GenerationType.IDENTITY)//主键自增
    21. private Integer id;
    22. private String name;
    23. private Double price;
    24. private String author;
    25. //如果需要排除掉@Transient
    26. }

    持久层接口

    1. package com.example.dao;
    2. import com.example.pojo.Book;
    3. import org.springframework.data.repository.CrudRepository;
    4. /**
    5. * @author hrui
    6. * @date 2023/10/1 4:46
    7. */
    8. //继承CrudRepository 泛型写实体类 主键类型
    9. public interface BookDao extends CrudRepository<Book,Integer> {
    10. }

    业务层接口

    1. package com.example.service;
    2. import com.example.pojo.Book;
    3. import java.util.List;
    4. /**
    5. * @author hrui
    6. * @date 2023/10/1 2:06
    7. */
    8. public interface BookService {
    9. int addBook(Book book);
    10. List getAllBooks();
    11. void deleteBook(Integer id);
    12. }

    业务实现类

    1. package com.example.service.impl;
    2. import com.example.dao.BookDao;
    3. import com.example.pojo.Book;
    4. import com.example.service.BookService;
    5. import org.springframework.stereotype.Service;
    6. import org.springframework.transaction.annotation.Transactional;
    7. import java.util.List;
    8. /**
    9. * @author hrui
    10. * @date 2023/10/1 2:06
    11. */
    12. @Service
    13. @Transactional
    14. public class BookServiceImpl implements BookService {
    15. private BookDao bookDao;
    16. public BookServiceImpl(BookDao bookDao) {
    17. this.bookDao = bookDao;
    18. }
    19. @Override
    20. public int addBook(Book book) {
    21. bookDao.save(book);//执行后会将主键id传回封装到book
    22. return book.getId();
    23. }
    24. @Override
    25. public List getAllBooks() {
    26. return (List) bookDao.findAll();
    27. }
    28. @Override
    29. public void deleteBook(Integer id) {
    30. bookDao.deleteById(id);
    31. }
    32. }

    控制器

    1. package com.example.controller;
    2. import com.example.pojo.Book;
    3. import com.example.service.BookService;
    4. import org.springframework.http.HttpStatus;
    5. import org.springframework.http.ResponseEntity;
    6. import org.springframework.stereotype.Controller;
    7. import org.springframework.ui.Model;
    8. import org.springframework.web.bind.annotation.*;
    9. import java.util.HashMap;
    10. import java.util.Map;
    11. /**
    12. * @author hrui
    13. * @date 2023/9/30 22:44
    14. */
    15. @Controller
    16. public class BookController {
    17. private BookService bookService;
    18. public BookController(BookService bookService) {
    19. this.bookService = bookService;
    20. }
    21. @PostMapping("/addBook")
    22. public String addBook(Book book,Model model){
    23. if(bookService.addBook(book)>0){
    24. return "redirect:listBooks";//重定向
    25. }
    26. model.addAttribute("tip", "添加图书失败");
    27. return "bookForm";
    28. }
    29. @GetMapping("/bookForm")
    30. public String bookForm(){
    31. return "bookForm";
    32. }
    33. @RequestMapping("/listBooks")
    34. public String list(Model model){
    35. //查询系统中所有的图书 存入books属性
    36. model.addAttribute("books", bookService.getAllBooks());
    37. return "listBooks";//转发
    38. }
    39. @RequestMapping("/deleteBook/{id}")
    40. public String delete(@PathVariable Integer id,Model model){
    41. bookService.deleteBook(id);
    42. return "redirect:/listBooks";
    43. }

    resources/templates/下的3个文件

    hello.html

    1. <!DOCTYPE html>
    2. <!--导入thymeleaf-->
    3. <html lang="en" xmlns:th="http://www.thymeleaf.org">
    4. <head>
    5. <meta charset="UTF-8">
    6. <title>欢迎页面</title>
    7. <!--引入webjar中bootstrap样式-->
    8. <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.6.0/css/bootstrap.css}">
    9. </head>
    10. <body>
    11. <div class="container">
    12. <div th:text="${tip}" class="alert alert-primary">提示信息</div>
    13. </div>
    14. </body>
    15. </html>

    bookForm.html

    1. <!DOCTYPE html>
    2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>添加图书</title>
    6. <!-- 导入Webjar中的Boostrap资源 -->
    7. <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.6.0/css/bootstrap.css}">
    8. </head>
    9. <body>
    10. <div class="container">
    11. <!-- 使用th:text将表达式的值绑定到标准HTML元素 -->
    12. <div class="alert alert-primary" th:text="${tip}">提示信息</div>
    13. <h2>添加图书</h2>
    14. <form method="post" th:action="@{/addBook}">
    15. <div class="form-group row">
    16. <label for="name" class="col-sm-3 col-form-label">图书名:</label>
    17. <div class="col-sm-9">
    18. <input type="text" id="name" name="name"
    19. class="form-control" placeholder="输入图书名">
    20. </div>
    21. </div>
    22. <div class="form-group row">
    23. <label for="author" class="col-sm-3 col-form-label">作者:</label>
    24. <div class="col-sm-9">
    25. <input type="text" id="author" name="author"
    26. class="form-control" placeholder="输入作者">
    27. </div>
    28. </div>
    29. <div class="form-group row">
    30. <label for="price" class="col-sm-3 col-form-label">价格:</label>
    31. <div class="col-sm-9">
    32. <input type="number" step="0.1" id="price" name="price"
    33. class="form-control" placeholder="输入价格">
    34. </div>
    35. </div>
    36. <div class="form-group row">
    37. <div class="col-sm-6 text-right">
    38. <button type="submit" class="btn btn-primary">添加</button>
    39. </div>
    40. <div class="col-sm-6">
    41. <button type="reset" class="btn btn-danger">重设</button>
    42. </div>
    43. </div>
    44. </form>
    45. </div>
    46. </body>
    47. </html>

    listBooks.html

    1. <!DOCTYPE html>
    2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>欢迎页面</title>
    6. <!-- 导入Webjar中的Boostrap资源 -->
    7. <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.6.0/css/bootstrap.css}">
    8. </head>
    9. <body>
    10. <div class="container">
    11. <table class="table table-hover">
    12. <tr>
    13. <th>书名</th>
    14. <th>价格</th>
    15. <th>作者</th>
    16. <th>删除</th>
    17. </tr>
    18. <tr th:each="book: ${books}">
    19. <td th:text="${book.name}">书名</td>
    20. <td th:text="${book.price}">价格</td>
    21. <td th:text="${book.author}">作者</td>
    22. <td><a th:href="@{/deleteBook/} + ${book.id}">删除</a></td>
    23. </tr>
    24. </table>
    25. <div class="text-right"><a class="btn btn-primary" th:href="@{/bookForm}">添加图书</a></div>
    26. </div>
    27. </body>
    28. </html>

    效果

    访问localhost:8080/bookForm

    点击添加

    08.SpringBoot对单元测试的支持

    复制个新的springboot-003

    添加SpringBoot的测试依赖,这个依赖原先就放进去了

    
        org.springframework.boot
        spring-boot-starter-test
        test
    

    在控制器新增几个方法

    @PostMapping("/books")
    @ResponseBody
    public ResponseEntity restAddBook(@RequestBody Book book){
        if(bookService.addBook(book)>0){
            return new ResponseEntity<>(book,HttpStatus.OK);
        }
        return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
    }
    
    @GetMapping("/books")
    @ResponseBody
    public ResponseEntity> restList(){
        return new ResponseEntity<>(bookService.getAllBooks(), HttpStatus.OK);
    }
    
    @DeleteMapping("/books/{id}")
    public ResponseEntity restDelete(@PathVariable Integer id){
        bookService.deleteBook(id);
        return new ResponseEntity<>(id, HttpStatus.OK);
    }
    

    1.用postman测试

    Post      http://localhost:8080/books

    Get      http://localhost:8080/books  body体里不管,反正后端没接收

    Delete   http://localhost:8080/books/7

    2.使用TestRestTemplate测试RESTFUL接口

    测试类使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)修饰

    Spring整合Junit5 出了方法上加@Test之外 还可以使用

    @ParameterizedTest
    @CsvSource({"Tomcat与Java web,111.0,孙卫琴","Vue.js,128,杜聚宾"})
    public void testAddBook2(String name,double price,String author){
        Book book=new Book(null,name,price,author);
        Book resBook = testRestTemplate.postForObject("/books", book, Book.class);
        System.out.println(resBook);
        //使用断言
        Assertions.assertEquals("Spring data jpa", resBook.getName());
        Assertions.assertEquals(129.0, resBook.getPrice());
    }
    
    
    @ParameterizedTest
    @ValueSource(ints = {9, 10, 11})
    void testIsPositive(Integer id) {
        testRestTemplate.delete("/books/{id}",id);
    }
    
    @Test
    public void testList(){
        var forObject = testRestTemplate.getForObject("/books", List.class);
        forObject.forEach(System.out::println);
    
    }

    测试类

    1. package com.example;
    2. import com.example.pojo.Book;
    3. import lombok.var;
    4. import org.junit.jupiter.api.Assertions;
    5. import org.junit.jupiter.api.Test;
    6. import org.junit.jupiter.params.ParameterizedTest;
    7. import org.junit.jupiter.params.provider.CsvSource;
    8. import org.junit.jupiter.params.provider.MethodSource;
    9. import org.junit.jupiter.params.provider.ValueSource;
    10. import org.springframework.beans.factory.annotation.Autowired;
    11. import org.springframework.boot.test.context.SpringBootTest;
    12. import org.springframework.boot.test.web.client.TestRestTemplate;
    13. import org.springframework.util.Assert;
    14. import java.util.List;
    15. //@SpringBootTest
    16. @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
    17. class Springboot001ApplicationTests {
    18. @Autowired
    19. private TestRestTemplate testRestTemplate;
    20. @Test
    21. public void testAddBook(){
    22. Book book=new Book(null,"Spring data jpa",129.0,"xxx");
    23. Book resBook = testRestTemplate.postForObject("/books", book, Book.class);
    24. System.out.println(resBook);
    25. //使用断言
    26. Assertions.assertEquals("Spring data jpa", resBook.getName());
    27. Assertions.assertEquals(129.0, resBook.getPrice());
    28. }
    29. @ParameterizedTest
    30. @CsvSource({"Tomcat与Java web,111.0,孙卫琴","Vue.js,128,杜聚宾"})
    31. public void testAddBook2(String name,double price,String author){
    32. Book book=new Book(null,name,price,author);
    33. Book resBook = testRestTemplate.postForObject("/books", book, Book.class);
    34. System.out.println(resBook);
    35. //使用断言
    36. Assertions.assertEquals("Spring data jpa", resBook.getName());
    37. Assertions.assertEquals(129.0, resBook.getPrice());
    38. }
    39. @ParameterizedTest
    40. @ValueSource(ints = {9, 10, 11})
    41. void testIsPositive(Integer id) {
    42. testRestTemplate.delete("/books/{id}",id);
    43. }
    44. @Test
    45. public void testList(){
    46. var forObject = testRestTemplate.getForObject("/books", List.class);
    47. forObject.forEach(System.out::println);
    48. }
    49. // @ParameterizedTest
    50. // @MethodSource("xxx某个方法") 有兴趣自己查下
    51. @Test
    52. void contextLoads() {
    53. }
    54. }

    3.模拟Web环境测试控制器(暂时理解成测试转发或重定向的一些接口)

    不需要真正启动Web服务器,只是对Web环境进行简单的模拟.

    使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

    和@AutoConfigureMockMvc修饰测试用例

    测试用例类定义接收依赖注入的MockMvc类型的实例变量,通过该实例变量可模拟浏览器来发送请求,获取返回值ModelAndView

    新建测试类

    package com.example;
    
    import com.example.pojo.Book;
    import lombok.var;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.CsvSource;
    import org.junit.jupiter.params.provider.ValueSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.web.client.TestRestTemplate;
    import org.springframework.test.web.servlet.MockMvc;
    
    import java.util.List;
    
    
    @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
    @AutoConfigureMockMvc
    class Springboot001ApplicationTests2 {
    
    
        @Autowired
        private MockMvc mockMvc;
    
    
    }

    4.测试Service

    1. package com.example;
    2. import com.example.pojo.Book;
    3. import lombok.var;
    4. import org.junit.jupiter.api.Assertions;
    5. import org.junit.jupiter.api.Test;
    6. import org.junit.jupiter.params.ParameterizedTest;
    7. import org.junit.jupiter.params.provider.CsvSource;
    8. import org.junit.jupiter.params.provider.ValueSource;
    9. import org.springframework.beans.factory.annotation.Autowired;
    10. import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    11. import org.springframework.boot.test.context.SpringBootTest;
    12. import org.springframework.boot.test.web.client.TestRestTemplate;
    13. import org.springframework.test.web.servlet.MockMvc;
    14. import org.springframework.test.web.servlet.ResultActions;
    15. import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    16. import org.springframework.web.servlet.ModelAndView;
    17. import java.util.List;
    18. @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
    19. @AutoConfigureMockMvc
    20. class Springboot001ApplicationTests2 {
    21. @Autowired
    22. private MockMvc mockMvc;
    23. @Test
    24. public void testIndex() throws Exception {
    25. //发送请求,获取控制器方法返回的ModelAndView
    26. ModelAndView mv = mockMvc.perform(MockMvcRequestBuilders.get("/index")).andReturn().getModelAndView();
    27. Object tip = mv.getModel().get("tip");//放在model的里东西
    28. Assertions.assertEquals("第一个SpringBoot应用", tip);
    29. String viewName = mv.getViewName();//返回的视图组件
    30. Assertions.assertEquals("hello", viewName);
    31. }
    32. }

  • 相关阅读:
    linux网络协议栈源码分析 - 链路层ARP地址解析协议
    FFmpeg修复受损视频
    iOS经典面试题之深入解析分类Category的本质以及如何被加载
    Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。
    javaweb 通过JDBC连接Mysql 数据库
    基于ssm+jsp(非maven)的农产品购物系统
    Android提取视频或音频
    Java基础 --- Array和List互相转换
    C# 时区时间与本地时间的相互转换
    Codeforces Round #833 (Div. 2) B. Diverse Substrings
  • 原文地址:https://blog.csdn.net/tiantiantbtb/article/details/133440576