Spring Boot 學習筆記

来源:https://www.cnblogs.com/luisblog/archive/2022/10/28/16837176.html
-Advertisement-
Play Games

SpringBoot 簡介 為什麼要使用 Spring Boot 因為 Spring,SpringMVC 需要使用的大量的配置文件 (xml文件) 還需要配置各種對象,把使用的對象放入到 spring 容器中才能使用對象 需要瞭解其他框架配置規則。 SpringBoot 就相當於 不需要配置文件的 ...


SpringBoot 簡介

  1. 為什麼要使用 Spring Boot

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

    還需要配置各種對象,把使用的對象放入到 spring 容器中才能使用對象

    需要瞭解其他框架配置規則。

  2. SpringBoot 就相當於 不需要配置文件的 Spring+SpringMVC。 常用的框架和第三方庫都已經配置好了。

    拿來就可以使用了。

  3. SpringBoot開發效率高,使用方便多了

JavaConfig

使用 java 類作為 xml 配置文件的替代, 是配置 spring 容器的純 java 的方式。

在這個 java 類中可以創建 java 對象,把對象放入 spring 容器中(註入到容器)。

對於此JavaConfig相關的示例創建的是普通的Java項目,並非SpringBoot項目!

@Configuration

  • 放在類的上面,表示此類作為配置文件使用,相當於一個配置類

@Bean

  • 放在配置類中的方法上面,用來聲明對象,將對象註入到容器中
  • 方法返回值需要是註入的對象類型
  • 若沒有配置@Bean中的 name 屬性,則從容器中獲取該對象需要用其方法名
  • 若配置了@Bean中的 name 屬性,則從容器中獲取該對象需要用配置的 name 名稱

需要使用到兩個註解:

  • @Configuration:放在一個類的上面,表示這個類是作為配置文件使用的。
  • @Bean:放在配置類中的方法上,聲明對象,把對象註入到容器中。

配置類示例:

/**
 * Configuration:表示當前類是作為配置文件使用的。 就是用來配置容器的
 *       位置:在類的上面
 *
 *  SpringConfig這個類就相當於beans.xml
 */
@Configuration
public class SpringConfig {

    /**
     * 創建方法,方法的返回值是對象。 在方法的上面加入@Bean
     * 方法的返回值對象就註入到容器中。
     *
     * @Bean: 把對象註入到spring容器中。 作用相當於<bean>
     *
     *     位置:方法的上面
     *
     *     說明:@Bean,不指定對象的名稱,預設是方法名是 id
     *
     */
    @Bean
    public Student createStudent(){
        Student s1  = new Student();
        s1.setName("張三");
        s1.setAge(26);
        s1.setSex("男");
        return s1;
    }

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

測試:

public class MyTest {

    @Test
    public void test01() {
        // 使用配置文件方式聲明的bean,需要用 ClassPathXmlApplicationContext,參數傳配置文件路徑
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("myStudent");
        System.out.println(student);
    }

    @Test
    public void test02() {
        // 使用配置類方式將對象註入到容器,需要使用 AnnotationConfigApplicationContext,參數傳配置類的class 
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 配置類中方法的Bean設置name屬性,則通過name屬性名獲取對象;否則預設可通過其方法名獲取
        Student s = (Student) ctx.getBean("lisiStudent");
        // Student s = (Student) ctx.getBean("makeStudent");
        // Student s = (Student) ctx.getBean("createStudent");
        System.out.println(s);
    }
}

小結:

  • 使用配置類的方式,需要在配置類上使用@Configuration;需要在配置類中的方法上使用@Bean聲明對象,將對象註入到容器中。
  • 配置類中的方法返回值類型是需要註入的對象類型;若未配置@Bean中的 name 屬性,則獲取該對象時需要使用方法名獲取;若配置了@Bean中的 name 屬性,則通過配置的 name 名稱獲取該對象。
  • 創建容器對象時,不再使用ClassPathXmlApplicationContext介面實現類,不再通過配置文件來註入到容器對象中;而是使用AnnotationConfigApplicationContext介面實現類,通過配置類的 class 來將對象註入到容器。

@ImportResource

  • 使用在配置類的上面
  • 作用是導入其他的 xml 配置文件, 等於在 xml 中使用 <import resources="其他配置文件"/>
  • 需要在 value 屬性中指定配置文件的路徑
@Configuration
@ImportResource(value = "classpath:applicationContext.xml")
public class SpringConfig {
}

@PropertySource

  • 使用在配置類的上面
  • 用來讀取 properties 屬性配置文件
  • 使用屬性配置文件可以實現外部化配置 ,在程式代碼之外提供數據。

@ComponentScan:使用在配置類上,掃描指定包中註解,來創建對象以及給屬性賦值

示例:

--配置類--
@Configuration
@ImportResource(value = "classpath:applicationContext.xml")  // 導入xml配置文件
@PropertySource(value = "classpath:config.properties")  // 讀取屬性配置文件
@ComponentScan(basePackages = "com.luis.vo")  // 聲明組件掃描器,掃描指定包中的註解
public class SpringConfig {
}

--config.properties--
tiger.name=東北虎
tiger.age=3 

--vo數據類--    
@Component("tiger")
public class Tiger {

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

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

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

SpringBoot 入門

SpringBoot 是 Spring 中的一個成員,可簡化 Spring,SpringMVC 的使用。

其核心還是 IOC 容器。

SpringBoot 特點

  • Create stand-alone Spring applications

    創建 spring 應用

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

    有內嵌的 tomcat,jetty,Undertow

  • Provide opinionated 'starter' dependencies to simplify your build configuration

    提供了 starter 起步依賴,簡化應用的配置。

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

    如今在 SpringBoot 項目中,在 pom.xml 裡面,只需加入一個 mybatis-spring-boot-starter 依賴即可

  • Automatically configure Spring and 3rd party libraries whenever possible

    儘可能去配置 spring 和第三方庫,也叫做自動配置(就是把 spring 中的,第三方庫中的對象都創建好,放到容器中,開發人員可以直接使用)

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

    提供了健康檢查,統計,外部化配置

  • Absolutely no code generation and no requirement for XML configuration

    不用生成代碼,不用使用xml,做配置

創建 SpringBoot 項目的三種方式

創建 SpringBoot 項目有三種方式:

  1. 使用 Spring 提供的初始化器,就是使用嚮導創建 SpringBoot 應用(使用 https://start.spring.io 地址)【聯網】

  2. 使用 Spring 提供的初始化器,就是使用嚮導創建 SpringBoot 應用(使用國內的 https://start.springboot.io 地址)【聯網】

    還可以選擇使用阿裡雲的地址進行創建:https://start.aliyun.com

  3. 先直接創建 maven 項目,然後補充相關依賴,補全目錄結構即可【不需聯網】

創建簡單 SpringBoot web 項目示例:(以下選擇嚮導方式創建)

  1. 新建 SpringBoot 模塊,選擇 Spring Initializr嚮導創建

  2. 配置項目相關信息,依賴選擇 Spring Web 進行創建

  3. 整理項目結構以及 pom 文件

  4. 在主啟動類所在的包下創建 controller 控制器類

    @Controller
    public class HelloSpringBoot {
    
        @RequestMapping("/hello")
        @ResponseBody
        public String helloSpringBoot() {
            return "歡迎使用SpringBoot";
        }
    }
    
  5. 查看是否配置有 Spring Boot 啟動服務,若沒有則進行配置

  6. 運行主啟動類的 main 方法或 IDEA 主面板運行項目

  7. 瀏覽器輸入地址訪問 http://localhost:8080/hello(預設8080埠,無上下文)

@SpringBootApplication

  • 其自動配置在主類之上,每個 SpringBoot 項目都會有一個主類

    @SpringBootApplication
    public class SpringbootTest03Application {
        public static void main(String[] args) {
            SpringApplication.run(SpringbootTest03Application.class, args);
        }
    }
    
@SpringBootApplication
是一個複合註解,包含以下三個註解(以下註解的功能其全具備)
@SpringBootConfiguration  -----> 該註解標註的類可當做配置類使用
@EnableAutoConfiguration  -----> 啟用自動配置,將常用框架以及第三方對象創建好
@ComponentScan  -----> 可掃描到該註解標註的類的包及其子包下其他註解
    
詳解:    
1.@SpringBootConfiguration
    
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
說明:使用了@SpringBootConfiguration註解標註的類,可以作為配置文件使用,
    可以使用@Bean聲明對象,註入到容器,
    故主類可作為一個配置類使用,在其類中可在方法上使用@Bean聲明對象

2.@EnableAutoConfiguration
啟用自動配置,把java對象配置好,註入到spring容器中;例如可以把mybatis的對象創建好,放入到容器中。
    
3.@ComponentScan 
掃描器,找到註解,根據註解的功能創建對象,給屬性賦值等。
預設掃描的包: @ComponentScan所標註的類所在的包和子包。    

SpringBoot 的配置文件

避免中文亂碼,需要在 IDEA 中設置 encoding 為 UTF-8

配置文件名: application

擴展名有:properties( k=v) 以及 yml ( k: v)

可使用 application.properties,application.yml 兩種文件格式

創建 SpringBoot 項目時預設創建的是 application.properties 配置文件格式

以下為配置示例:

例1:application.properties 中設置埠和上下文

# 設置埠
server.port=8888
# 設置訪問應用的上下文路徑
server.servlet.context-path=/myWeb

例2:application.yml 中設置埠和上下文(推薦使用

這種格式的配置文件,結構比較清晰

註意:value 值前有一個空格

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

註意:如果同時存在兩種格式的配置文件,即 application.properties 和 application.yml 兩個配置文件同時存在,則預設使用 application.properties 這種格式中的配置!

多環境配置的應用

有開發環境,測試環境,上線的環境。

每種環境有不同的配置信息,例如埠,上下文訪問路徑,資料庫 url,用戶名,密碼等,所以需要多種環境配置。

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

多環境配置方式

  1. 創建多個配置文件,文件命名規則:application-環境名稱.properties(yml)【一般環境名使用 dev/test/online 這幾種】

    創建開發環境的配置文件:application-dev.yml

    #項目開發使用的環境
    server:
      port: 8080
      servlet:
        context-path: /mydev
    

    創建測試環境的配置文件:application-test.yml

    #項目測試使用的環境
    server:
      port: 8081
      servlet:
        context-path: /mytest
    

    創建上線環境的配置文件:application-online.yml

    #項目上線使用的環境
    server:
      port: 8082
      servlet:
        context-path: /myonline
    
  2. 在主配置文件 application.yml 中激活要使用的環境【激活的配置信息是根據多環境文件的命名來確定】

    主配置文件中激活要使用的環境:application.yml

    #激活使用的環境
    spring:
      profiles:
        active: online
    

使用 @Value 讀取配置文件數據

我們可以在主配置文件中使用 key-value 鍵值對的格式進行數據的配置;

因為主配置文件已經由 Spring 自動管理,所以可以直接在自己寫的控制器類的屬性上通過 @Value("${server.port}")讀取配置文件中數據,並對屬性進行賦值。

@Controller
public class MyController {

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

    @RequestMapping("/data")
    @ResponseBody
    public String queryData() {
        return port + "========> port " + contextPath + "========> contextPath "
                + projectName + "========> projectName " + projectDev + "========> projectDev";
    }
}

@ConfigurationProperties

  • 使用位置:類的上面
  • 作用:把配置文件中符合條件的數據映射為 java 對象
  • 需要配置其 prefix 屬性:即配置文件中的某些 key 開頭的內容

使用示例:@ConfigurationProperties(prefix = "school")

使用解釋:類上添加@ConfigurationProperties註解後,其將從屬性配置文件中找以配置的 prefix 屬性值,即school開頭的配置,將所有 school後面的配置參數與該類中的所有屬性相比較,如果匹配成功,則將配置文件中配置的對應的數據賦值給該類中同名屬性,完成數據映射。

使用示例:

  1. 在配置文件 application.properties 中配置自定義數據

    #配置埠號
    server.port=8888
    #配置上下文訪問路徑
    server.servlet.context-path=/myboot
    
    #自定義數據
    school.name=哈師大
    school.addr=東北
    school.level=2
    
  2. 創建數據對象

    @Component
    @ConfigurationProperties(prefix = "school")
    public class SchoolInfo {
    
        private String name;
        private String addr;
        private Integer level;
        // getter,setter,toString...
    }    
    
  3. 創建控制器類

    @Controller
    public class MyController {
    
        @Resource
        private SchoolInfo info;
    
        @RequestMapping("/info")
        @ResponseBody
        public String querySchoolInfo() {
            return "info = " + info;
        }
    }
    
  4. 運行,訪問測試

    訪問:http://localhost:8888/myboot/info
    結果:info = SchoolInfo{name='哈師大', addr='東北', level=2}
    

SpringBoot 中使用 JSP(不推薦,瞭解即可)

SpringBoot 預設不支持 JSP,需要進行相關配置才能使用 JSP。

JSP 技術慢慢被淘汰,有更好的技術替代它。

使用 SpringBoot 框架時不推薦使用 JSP,後面將使用 Thymeleaf 模板技術完全替代 JSP!

使用步驟:

  1. 創建 SpringBoot 項目,整理項目結構和 pom 文件

  2. 添加一個處理 JSP 的依賴,負責編譯 JSP 文件(如果需要使用 servlet jsp jstl 功能則需要另外加對應依賴)

    <!--處理JSP的依賴-->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>
    
    <dependency>
    	<groupId>javax.servlet</groupId>
    	<artifactId>jstl</artifactId>
    </dependency>
    
    <dependency>
    	<groupId>javax.servlet</groupId>
    	<artifactId>javax.servlet-api</artifactId>
    </dependency>
    
    <dependency>
    <groupId>javax.servlet.jsp</groupId>
    	<artifactId>javax.servlet.jsp-api</artifactId>
    	<version>2.3.1</version>
    </dependency>
    
  3. 在 main 目錄下創建一個名為 webapp 的目錄(名稱固定);在項目工程結構中設置該目錄為 web 資源目錄(進入項目結構設置後,點擊 Web 選項,從 Web Resource Directories 下添加新創建的 webapp 目錄為 web 資源目錄即可)

  4. 在 webapp 目錄下新建 index.jsp 用來顯示 controller 中的數據

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>jsp</title>
    </head>
    <body>
        SpringBoot中使用JSP顯示數據:${data}
    </body>
    </html>
    
  5. 創建 controller 控制器類,指定數據和視圖

    @Controller
    public class JspController {
    
        @RequestMapping("/myjsp")
        public String doJsp(Model model) {
            // 將數據放到request中(與request.setAttribute作用相同)
            model.addAttribute("data", "SpringBoot使用JSP");
            return "index";
        }
    }
    
  6. 配置文件中配置視圖解析器,埠號以及上下文等信息

    #配置埠號
    server.port=7070
    #配置上下文訪問路徑
    server.servlet.context-path=/myboot
    
    #配置視圖解析器
    # / = src/main/webapp
    spring.mvc.view.prefix=/
    spring.mvc.view.suffix=.jsp
    
  7. 在 pom.xml 中指定 jsp 文件編譯後的存放目錄【在 pom 的 build 標簽下進行指定】

    修改 pom 文件後,記得重新載入下,確保 pom 文件資源完全刷新!

    <!-- 指定jsp編譯後的存放目錄 -->
    <resources>
        <resource>
            <!-- jsp原來的目錄 -->
            <directory>src/main/webapp</directory>
            <!-- 指定編譯後的存放目錄 -->
            <targetPath>META-INF/resources</targetPath>
            <!-- 指定治理後的目錄和文件 -->
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
    </resources>
    
  8. 直接運行並啟動主程式,輸入地址訪問測試

    http://localhost:7070/myboot/myjsp
    

兩點需要註意下:

  • 必須添加處理 jsp 的依賴
  • 必須指定 jsp 編譯後的存放目錄

原因:因為 SpringBoot 使用的是內嵌的 Tomcat

SpringBoot 使用容器 ApplicationContext

使用場景:不想啟動整個項目,只想測試某個功能,就可直接通過run方法獲取容器對象,通過容器對象進行相關測試。

如果想通過代碼,從容器中獲取對象:

通過SpringApplication.run(Application.class, args); 其返回值即可獲取容器對象。

SpringApplication.run(SpringbootUseJspApplication.class, args)返回的就是一個 ApplicationContext 容器對象!

解析:SpringApplication.run(SpringbootUseJspApplication.class, args);

點進其run方法:
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}   

查看ConfigurableApplicationContext類:
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {...}    

總結:通過run方法獲取的是容器對象ApplicationContext的子類,即也是一個容器對象。

容器使用示例:

  1. 創建 SpringBoot 項目時選擇 Spring Web 依賴,整理項目目錄和 pom 文件

  2. 創建 service 介面及其實現類,定義測試方法

    public interface UserService {
        void sayHello(String name);
    }
    
    @Service("userService")
    public class UserServiceImpl implements UserService {
    
        @Override
        public void sayHello(String name) {
            System.out.println("hello " + name);
        }
    }
    
  3. 在主啟動類中直接獲取並使用容器對象進行測試

    @SpringBootApplication
    public class SpringbootUseContainerApplication {
    
        public static void main(String[] args) {
            // 直接通過run方法獲取容器對象
            ApplicationContext ctx = SpringApplication.run(SpringbootUseContainerApplication.class, args);
            // 從容器中獲取指定對象
            UserService userService = (UserService) ctx.getBean("userService");
            // 調用對象的方法進行測試
            userService.sayHello("luis");
        }
    }
    

CommandLineRunner 和 ApplcationRunner 介面

介紹:這兩個介面都有一個 run 方法。

執行時機:容器對象創建好後自動會執行介面中的 run() 方法

使用場景:需要在容器啟動後執行一些內容,比如讀取配置文件,資料庫連接之類的。

使用方式:實現介面,重寫 run 方法,方法中寫需要在容器啟動後待執行的內容。

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

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

使用示例:(以下以實現 CommandLineRunner介面為例)

  1. 創建 SpringBoot 項目,不用選擇依賴,整理項目目錄和 pom 文件

  2. 新建 service 介面以及實現類,定義測試方法

    public interface UserService {
        void sayHello(String name);
    }
    
    @Service("userService")
    public class UserServiceImpl implements UserService {
        @Override
        public void sayHello(String name) {
            System.out.println("你好," + name);
        }
    }
    
  3. 讓啟動類實現 CommandLineRunner介面,重寫 run 方法進行測試

    @SpringBootApplication
    public class SpringbootRunApplication implements CommandLineRunner {
    
        @Resource
        private UserService userService;
    
        public static void main(String[] args) {
            System.out.println("main start");
            // 創建容器對象
            SpringApplication.run(SpringbootRunApplication.class, args);
            System.out.println("main end");
        }
    
        @Override
        public void run(String... args) throws Exception {
            System.out.println("容器對象創建後執行此run方法");
            // 此方法在容器對象創建後自動執行
            // 可在此調用容器對象中的方法
            userService.sayHello("jack");
        }
    }
    
  4. 運行主程式,進行測試

    運行結果:

    main start
    容器對象創建後執行此run方法
    你好,jack
    main end
    

SpringBoot 和 Web 組件

講三個內容:攔截器、Servlet、Filter

SpringBoot 中使用攔截器

攔截器是 SpringMVC 中的一種對象,能攔截對 Controller 的請求。

在框架中有系統實現好的攔截器, 也可以自定義攔截器,實現對請求的預先處理。

回顧 SpringMVC 中使用攔截器

  1. 創建類實現 SpringMVC 框架的 HandlerInterceptor 介面,重寫對應的方法

    public interface HandlerInterceptor {
     default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         return true;
     }
    
     default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
     }
    
     default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
     }
    }
    
  2. 在 SpringMVC 的配置文件中,聲明攔截器

    <mvc:interceptors>
    	<mvc:interceptor>
        	<mvc:path="url" />
            <bean class="攔截器類全限定名稱"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

SpringBoot 中使用攔截器

示例:

  1. 創建 SpringBoot 項目,選擇 Spring Web 依賴,整理項目目錄和 pom 文件

  2. 創建攔截器類,實現 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;
        }
    }
    
  3. 創建自定義配置類實現 WebMvcConfigurer介面,重寫addInterceptors介面方法,在此方法中進行攔截器的相關配置(註入攔截器對象,指定攔截地址等)

    @Configuration // 成為配置類=====
    public class MyAppConfig implements WebMvcConfigurer {
    
        // 重寫addInterceptors方法,添加攔截器對象,註入到容器中
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            // 創建攔截器對象
            HandlerInterceptor loginInterceptor = new LoginInterceptor();
    
            // 指定攔截的請求URI地址
            String[] path = {"/user/**"};
            // 指定不攔截的URI地址
            String[] excludePath = {"/user/login"};
    
            // 添加攔截器對象,指定攔截以及不攔截的URI地址
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns(path)
                    .excludePathPatterns(excludePath);
        }
    }
    
  4. 創建控制器類,進行資源訪問攔截測試

    @Controller
    @RequestMapping("/user")
    public class BootController {
    
        @RequestMapping("/account")
        @ResponseBody
        public String userAccount() {
            return "訪問/user/account地址";
        }
    
        @RequestMapping("/login")
        @ResponseBody
        public String userLogin() {
            return "訪問/user/login地址";
        }
    }
    
  5. 運行主程式,進行訪問測試

    分別訪問下列兩個地址:
    http://localhost:8080/user/account
    http://localhost:8080/user/login
    訪問的測試結果:
    訪問http://localhost:8080/user/account時,後臺有攔截器攔截信息輸出【此請求走攔截器,被攔截器攔截】
    訪問http://localhost:8080/user/login時,後臺無攔截器攔截信息輸出【此請求不走攔截器,不會被攔截器攔截】
    

SpringBoot 中使用 Servlet

使用步驟:

  1. 創建 SpringBoot 項目,選擇 Spring Web 依賴,整理項目目錄和 pom 文件

  2. 創建 servlet 類,繼承 HttpServlet,重寫相關方法

    public class MyServlet extends HttpServlet {
    
        // 直接重寫service方法,則doGet和doPost請求都直接走此方法
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            // 設置字元編碼
            response.setContentType("text/html;charset=UTF-8");
    
            // 使用應答對象HttpServletResponse,輸出應答結果
            PrintWriter out = response.getWriter();
            out.print("SpringBoot中使用Servlet");
            out.flush();
            out.close();
        }
    }
    
  3. 創建自定義配置類,在類中定義指定返回值類型的方法,註冊 Servlet 對象

    @Configuration
    public class WebApplicationConfig {
    
        // ====定義指定返回值類型的方法,註冊servlet對象====
        @Bean
        public ServletRegistrationBean servletRegistrationBean() {
    
            // 兩種方式註冊servlet:
    
            // 方式一:使用ServletRegistrationBean對象的有參構造
            // 下列對象構造方法參數:第一個是需要註冊的servlet對象,第二個是對應servlet的訪問地址
            // ServletRegistrationBean bean = new ServletRegistrationBean(new MyServlet(), "/login1", "/login2");
    
            // 方式二:使用ServletRegistrationBean對象的無參構造
            ServletRegistrationBean bean = new ServletRegistrationBean();
            bean.setServlet(new MyServlet());
            bean.addUrlMappings("/login3", "/login4");
            return bean;
        }
    }
    
  4. 運行主程式,輸入地址訪問測試

    http://localhost:8080/login1
    http://localhost:8080/login2
    http://localhost:8080/login3
    http://localhost:8080/login4
    

SpringBoot 中使用過濾器

Filter 是 Servlet 規範中的過濾器,可以處理請求,對請求的參數,屬性進行調整。

常常在過濾器中處理字元編碼。

SpringBoot 中使用過濾器 Filter:

使用步驟:

  1. 創建 SpringBoot 項目,選擇 Spring Web 依賴,整理項目目錄和 pom 文件,刷新 pom

  2. 創建自定義的過濾器類,實現 javax.servlet.Filter 介面,重寫 doFilter 方法(註意實現的是 servlet 中的 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);
        }
    }
    
  3. 創建自定義配置類,在類中定義指定返回值類型的方法,註冊過濾器對象

    @Configuration
    public class WebApplicationConfig {
    
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            
            // 註冊自定義過濾器類,並指定過濾的地址
            FilterRegistrationBean bean = new FilterRegistrationBean();
            bean.setFilter(new MyFilter());
            bean.addUrlPatterns("/user/*");
            return bean;
        }
    }
    
  4. 創建控制器類,進行資源訪問過濾測試

    @Controller
    public class CustomFilterController {
    
        @RequestMapping("/user/login")
        @ResponseBody
        public String userLogin() {
            return "訪問/user/login";
        }
    
        @RequestMapping("/query")
        @ResponseBody
        public String query() {
            return "訪問/query";
        }
    }
    
  5. 運行主啟動類,輸入訪問地址測試

    http://localhost:8080/query
    http://localhost:8080/user/login
    

SpringBoot 中使用字元集過濾器

一般,都是使用字元集過濾器 CharacterEncodingFilter解決 post 請求中文亂碼的問題。

CharacterEncodingFilter : 解決 post 請求中文亂碼的問題。

在 SpringMVC 框架, 需要在 web.xml 註冊過濾器並配置其相關屬性。

在SpringBoot 中使用字元集過濾器解決 post 請求亂碼有兩種方式:

使用示例:

  1. 創建 SpringBoot 項目,選擇 Spring Web 依賴,整理項目目錄和 pom 文件,刷新 pom

  2. 創建自定義 servlet,處理請求

    public class MyServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            response.setContentType("text/html"); // 此處並沒有設置字元編碼方式
    
            PrintWriter out = response.getWriter();
            out.write("沒有設置編碼方式,預設使用ISO-8859-1,會出現中文亂碼");
            out.flush();
            out.close();
        }
    }
    
  3. 創建自定義配置類,註冊 servlet,設置訪問路徑

    @Configuration
    public class WebSystemConfig {
    
        // 註冊servlet,設置訪問路徑
        @Bean
        public ServletRegistrationBean servletRegistrationBean() {
    
            ServletRegistrationBean bean = new ServletRegistrationBean();
            bean.setServlet(new MyServlet());
            bean.addUrlMappings("/myservlet");
            return bean;
        }
    }
    
  4. 啟動主程式,輸入訪問地址進行測試

    http://localhost:8080/myservlet
    結果:出現中文亂碼
    ?????????????ISO-8859-1????????
    

方式一:配置類中設置字元編碼(不推薦)

不僅需要在配置類中註冊字元集過濾器類,設置字元編碼,還需在配置文件中關閉預設啟用的過濾器。

  1. 在自定義配置類中需創建指定返回值類型的方法,註冊 CharacterEncodingFilter字元集過濾器類,設置字元編碼
@Configuration
public class WebSystemConfig {

    // 註冊servlet,設置訪問路徑
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {

        ServletRegistrationBean bean = new ServletRegistrationBean();
        bean.setServlet(new MyServlet());
        bean.addUrlMappings("/myservlet");
        return bean;
    }

    // ==================================================================
    // 註冊CharacterEncodingFilter,並設置字元編碼方式
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {

        FilterRegistrationBean reg = new FilterRegistrationBean();

        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        // 設置字元編碼方式
        filter.setEncoding("UTF-8");
        // 指定request,response都使用encoding的值
        filter.setForceEncoding(true);

        reg.setFilter(filter); // 註冊字元集過濾器對象CharacterEncodingFilter
        reg.addUrlPatterns("/*"); // 設置過濾地址

        return reg;
    }
    // ==================================================================    
}
  1. 修改 application.properties 文件,讓自定義的過濾器起作用

    #SpringBoot中預設已經配置了CharacterEncodingFilter。 編碼預設ISO-8859-1
    #設置enabled=false 作用是關閉系統中配置好的過濾器, 使用自定義的CharacterEncodingFilter
    server.servlet.encoding.enabled=false
    

方式二:配置文件中設置字元編碼(推薦)

只需要通過幾行配置,即可完成字元編碼的設置。

#讓系統的CharacterEncdoingFilter生效(預設為true)
server.servlet.encoding.enabled=true
#指定使用的編碼方式
server.servlet.encoding.charset=UTF-8
#強制request,response都使用charset屬性的值
server.servlet.encoding.force=true

ORM 操作 MySQL

ORM 是“對象-關係-映射”的簡稱。(Object Relational Mapping,簡稱ORM)

使用 MyBatis 框架操作 MySQL。

使用 MyBatis 框架操作數據,使用 SpringBoot 框架集成 MyBatis。

SpringBoot 集成 Mybatis

以下是集成步驟示例,創建 dao 介面的代理對象有好幾種方式可供選擇,以下方式並不完美,註意後續自己修改!

前期準備
資料庫名:springdb
資料庫表:student
欄位:id (int auto_increment) name(varchar) age(int)

步驟:

  1. 創建 SpringBoot 項目,添加 Spring Web、MyBatis、MySQL 依賴,整理項目目錄和 pom 文件,刷新 pom

  2. 創建實體類 model

    public class Student {
        private Integer id;
        private String name;
        private Integer age;
        // getter,setter,toString...
    }    
    
  3. 寫 dao 介面和 mapper 文件

    此處 dao 介面上使用了 @Mapper註解,告訴MyBatis這是 dao 介面,創建此介面的代理對象

    @Mapper  // 告訴MyBatis這是dao介面,創建此介面的代理對象
    public interface StudentDao {
    
        Student selectById(@Param("stuId") Integer id);
    }
    
    <?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.luis.dao.StudentDao">
    
        <select id="selectById" resultType="com.luis.model.Student">
            select id,name,age from student where id=#{stuId}
      </select>
    
    </mapper>
    
  4. 創建 service 介面及其實現類

    // 介面
    public interface StudentService {
    
        Student queryStudentById(Integer id);
    }
    
    // 實現類
    @Service
    public class StudentServiceImpl implements StudentService {
    
        @Resource
        private StudentDao studentDao;
    
        @Override
        public Student queryStudentById(Integer id) {
            return studentDao.selectById(id);
        }
    }
    
  5. 創建控制器類

    @Controller
    @RequestMapping("/student")
    public class StudentController {
        
        @Resource
        private StudentService studentService;
    
        @RequestMapping("/queryById")
        @ResponseBody
        public String queryStudentById(Integer id) {
            Student student = studentService.queryStudentById(id);
            return student.toString();
        }
    }
    
  6. 在 pom 文件的 build 標簽下添加 mapper 文件的 resources 插件

    <!--   resources插件,將mapper文件複製到classes目錄下     -->
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    
  7. 在主配置文件中配置埠,上下文訪問路徑,資料庫連接等信息

    server.port=8888
    server.servlet.context-path=/orm
    
    #配置資料庫連接信息 註意mysql新舊版本配置不同
    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=luis
    
  8. 運行啟動類,輸入訪問地址測試【註意:填的id必須資料庫中有,否則會出現空指針異常】

    http://localhost:8888/orm/student/queryById?id=29
    

日誌配置

在主配置文件中配置 mybatis 日誌:(可選不同的日誌列印,如選 log4j 這種的,則另需添加相關依賴)

# 日誌配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

第一種方式:使用@Mapper(不建議)

  • 使用在類上
  • 作用:告訴 MyBatis 這是 dao 介面,會自動創建此介面的代理對象
  • 缺點:每一個需要創建代理對象的 dao 介面都需要加上該註解,dao 介面多的時候不方便!

示例:

@Mapper  // 告訴MyBatis這是dao介面,創建此介面的代理對象
public interface StudentDao {

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

第二種方式:使用@MapperScan

  • 通常使用在主啟動類上
  • basePackages屬性:通常配置 dao 介面所在包名
  • 作用:找到 Dao 介面以及 Mapper 文件(可直接掃描到該包下所有的 dao 介面和 mapper 文件)
  • 優點:使用該註解直接掃描指定包,不用在每一個 dao 介面上分別加 @Mapper註解

示例:

@SpringBootApplication
@MapperScan(basePackages = "com.luis.dao") // 掃描指定包,找到dao介面和mapper文件,mybatis自動創建介面的代理對象
public class SpringbootMapperApplication {

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

}

第三種方式:Mapper文件和Dao介面分開管理(開發常用,推薦使用)

之前我們的 dao 目錄下既有 Java 文件,也有 xml/mapper 文件;如果希望 Java 目錄下只有 Java 文件,將 xml/mapper 文件放到 resources 下分開管理,那麼只使用之前的 @MapperScan註解是掃描不到 resources 下的 Mapper 文件的,此時我們就需要在配置文件中指定 Mapper 文件的位置。

示例:

操作:在 resources 下創建子目錄(自定義的),例如 mapper,用來存放 mapper 映射文件,將之前 dao 下的 mapper 文件全剪切到 mapper 目錄下。

  1. 同樣,我們仍然需要在主啟動類上使用 @MapperScan註解指定 dao 所在的包,掃描 dao 介面:
@SpringBootApplication
@MapperScan(basePackages = "com.luis.dao") // 掃描指定包,找到dao介面和mapper文件,mybatis自動創建介面的代理對象
public class SpringbootMapperApplication {

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

}
  1. 在主配置文件中指定 mapper 映射文件的位置:
#指定mapper文件的位置
mybatis.mapper-locations=classpath:mapper/*.xml
  1. 配置資源插件,確保資源文件編譯到 classes 目錄下:
<!--   resources插件,將所有資源文件複製到classes目錄下【配置在pom.xml的build標簽下】     -->
<resources>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.*</include>
        </includes>
    </resource>
</resources>

註意:如果項目編譯後 .xml/properties/yml 文件沒有出現在 classes 目錄下,則需要在 pom 中添加 resources 資源插件。

事務及mybatis自動代碼生成器的使用

回顧 Spring 框架中的事務:

  1. 管理事務的對象:事務管理器(介面,介面有很多的實現類)

    例如:使用 Jdbc 或 mybatis 訪問資料庫,使用的事務管理器:DataSourceTransactionManager

  2. 聲明式事務:使用 xml 配置文件或者使用註解說明事務控制的內容

    控制事務:隔離級別,傳播行為,超時時間

  3. 事務處理方式:

    1. Spring 框架中的 @Transactional
    2. Spring 支持 aspectj 框架的事務配置,可在 xml 配置文件中,聲明事務控制的內容

SpringBoot 中使用事務:上面的兩種方式都可以。

使用步驟:(以下以註解方式演示事務的使用:)

  1. 在業務方法的上面加入 @Transactional ,加註解後,方法就有事務功能

  2. 明確的在主啟動類的上面,加入@EnableTransactionManager,啟用事務管理器(可不用添加此註解

/**
     * @Transactional 表示方法有事務支持,拋出運行時異常,則進行回滾
     * 使用MySQL預設的傳播行為、隔離級別、超時時間
     */
@Transactional // 可通過屬性配置傳播行為、隔離級別、超時時間
@Override
public int addUser(User user) {
    System.out.println("業務方法addUser開始執行");
    int rows = userMapper.insert(user);
    System.out.println("業務方法addUser結束執行");

    // 模擬發生運行時異常
    // int num = 10 / 0;
    return rows;
}

SpringBoot 中通過註解使用事務,一句話說明:直接在需要開啟事務的業務方法上添加 @Transactional 註解即可!

示例:(有mybatis自動代碼生成器的使用示例,可自動生成 model 實體類, dao 介面以及 mapper 映射文件)

準備資料庫表:
資料庫名:springdb 表名:user
欄位:id(int auto_increment)name(varchar)age(int)
  1. 創建 SpringBoot 項目,添加 Spring Web、MyBatis、MySQL 依賴,整理項目目錄和 pom 文件

  2. 在 pom 的 plugins 標簽下添加 mybatis 自動代碼生成插件

    <!--mybatis自動代碼生成插件-->
    <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.6</version>
        <configuration>
            <!--配置文件的位置:在項目的根目錄下,和src平級-->
            <configurationFile>GeneratorMapper.xml</configurationFile>
            <verbose>true</verbose>
            <overwrite>true</overwrite>
        </configuration>
    </plugin>
    
  3. 在 pom 的 build 標簽下添加資源插件,處理資源文件,刷新 pom

    <!--   處理資源文件     -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/**.*</include>
            </includes>
        </resource>
    </resources>
    
  4. 在項目根目錄下創建 GeneratorMapper.xml文件,其與 src 平級;將下列內容拷貝到文件中;依照註釋修改配置,修改完後,點開右側 maven 快捷視窗,使用當前項目下 plugins 下 mybatis-genetate 下的 mybatis 自動代碼生成插件進行生成。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    <generatorConfiguration>
    
        <!-- 指定連接資料庫的JDBC驅動包所在位置,指定到你本機的完整路徑 -->
        <classPathEntry location="D:\Java\tools\mysql-connector-java-8.0.28.jar"/>
    
        <!-- 配置table表信息內容體,targetRuntime指定採用MyBatis3的版本 -->
        <context id="tables" targetRuntime="MyBatis3">
    
            <!-- 抑制生成註釋,由於生成的註釋都是英文的,可以不讓它生成 -->
            <commentGenerator>
                <property name="suppressAllComments" value="true" />
            </commentGenerator>
    
            <!-- 配置資料庫連接信息 -->
            <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                            connectionURL="jdbc:mysql://localhost:3306/springdb?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8"
                            userId="root"
                            password="luis">
                <!--MySQL 不支持 schema 或者 catalog 所以需要添加這個-->
                <!--設置原因參考:https://blog.csdn.net/qq_40233736/article/details/83314596-->
                <property name="nullCatalogMeansCurrent" value="true" />
            </jdbcConnection>
    
            <!-- 生成model類,targetPackage指定model類的包名, targetProject指定生成的model放在eclipse的哪個工程下麵-->
            <javaModelGenerator targetPackage="com.luis.model"
                                targetProject="D:\1a-Projects\springboot-projects\springboot-transactional\src\main\java">
                <property name="enableSubPackages" value="false" />
                <property name="trimStrings" value="false" />
            </javaModelGenerator>
    
            <!-- 生成MyBatis的Mapper.xml文件,targetPackage指定mapper.xml文件的包名, targetProject指定生成的mapper.xml放在eclipse的哪個工程下麵 -->
            <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
                <property name="enableSubPackages" value="false" />
            </sqlMapGenerator>
    
            <!-- 生成MyBatis的Mapper介面類文件,targetPackage指定Mapper介面類的包名, targetProject指定生成的Mapper介面放在eclipse的哪個工程下麵 -->
            <javaClientGenerator type="XMLMAPPER" targetPackage="com.luis.dao" targetProject="src/main/java">
                <property name="enableSubPackages" value="false" />
            </javaClientGenerator>
    
            <!-- 資料庫表名及對應的Java模型類名 -->
            <table tableName="user" domainObjectName="User"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
    
            <table tableName="b_bid_info" domainObjectName="BidInfo"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
    
    
            <table tableName="b_income_record" domainObjectName="IncomeRecord"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
    
    
            <table tableName="b_recharge_record" domainObjectName="RechargeRecord"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
    
    
            <table tableName="u_user" domainObjectName="User"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
    
    
            <table tableName="u_finance_account" domainObjectName="FinanceAccount"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false"/>
        </context>
    
    </generatorConfiguration>
    
  5. 主配置文件配置

    #配置埠
    server.port=9090
    #context-path
    server.servlet.context-path=/mytrans
    
    #資料庫連接配置
    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=luis
    
    #配置mapper文件路徑
    mybatis.mapper-locations=classpath:mapper/*.xml
    #開啟日誌
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
  6. 使用 mybatis 生成器生成的 model、dao、mapper 文件

    // model
    public class User {
        private Integer id;
        private String name;
        private Integer age;
        // get,set
    }
    
    // dao
    public interface UserMapper {
        int deleteByPrimaryKey(Integer id);
    
        int insert(User record);
    
        int insertSelective(User record);
    
        User selectByPrimaryKey(Integer id);
    
        int updateByPrimaryKeySelective(User record);
    
        int updateByPrimaryKey(User record);
    }
    
    <?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.luis.dao.UserMapper">
        <resultMap id="BaseResultMap" type="com.luis.model.User">
            <id column="id" jdbcType="INTEGER" property="id" />
            <result column="name" jdbcType="VARCHAR" property="name" />
            <result column="age" jdbcType="INTEGER" property="age" />
        </resultMap>
        <sql id="Base_Column_List">
            id, name, age
        </sql>
        <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
            select 
            <include refid="Base_Column_List" />
            from user
            where id = #{id,jdbcType=INTEGER}
        </select>
        <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
            delete from user
            where id = #{id,jdbcType=INTEGER}
        </delete>
        <insert id="insert" parameterType="com.luis.model.User">
            insert into user (id, name, age
            )
            values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}
            )
        </insert>
        <insert id="insertSelective" parameterType="com.luis.model.User">
            insert into user
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="id != null">
                    id,
                </if>
                <if test="name != null">
                    name,
                </if>
                <if test="age != null">
                    age,
                </if>
            </trim>
            <trim prefix="values (" suffix=")" suffixOverrides=",">
                <if test="id != null">
                    #{id,jdbcType=INTEGER},
                </if>
                <if test="name != null">
                    #{name,jdbcType=VARCHAR},
                </if>
                <if test="age != null">
                    #{age,jdbcType=INTEGER},
                </if>
            </trim>
        </insert>
        <update id="updateByPrimaryKeySelective" parameterType="com.luis.model.User">
            update user
            <set>
                <if test="name != null">
                    name = #{name,jdbcType=VARCHAR},
                </if>
                <if test="age != null">
                    age = #{age,jdbcType=INTEGER},
                </if>
            </set>
            where id = #{id,jdbcType=INTEGER}
        </update>
        <update id="updateByPrimaryKey" parameterType="com.luis.model.User">
            update user
            set name = #{name,jdbcType=VARCHAR},
            age = #{age,jdbcType=INTEGER}
            where id = #{id,jdbcType=INTEGER}
        </update>
    </mapper>
    
  7. 創建 service 介面及其實現類,在實現類的業務方法上添加 @Transactional註解,開啟事務支持

    public interface UserService {
        int addUser(User user);
    }
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Resource
        private UserMapper userMapper;
    
        /**
         * @Transactional 表示方法有事務支持,拋出運行時異常,則進行回滾
         * 使用MySQL預設的傳播行為、隔離級別、超時時間
         */
        @Transactional
        @Override
        public int addUser(User user) {
            System.out.println("業務方法addUser開始執行");
            int rows = userMapper.insert(user);
            System.out.println("業務方法addUser結束執行");
    
            // 模擬發生運行時異常
            int num = 10 / 0; // 測試時通過註釋以及放開觀察事務控制
            return rows;
        }
    }
    
  8. 創建控制器類

    @Controller
    public class UserController {
        
        @Resource
        private UserService userService;
    
        @RequestMapping("/addStudent")
        @ResponseBody
        public String addStudent(String name, Integer age) {
    
            User user = new User();
            user.setName(name);
            user.setAge(age);
            int rows = userService.addUser(user);
            return "添加結果:" + rows;
        }
    }
    
  9. 主啟動類上添加@EnableTransactionManagement註解,啟用事務管理器,與業務方法上的@Transactional配套使用;繼續在主啟動類上添加@MapperScan註解,指定dao所在的包,掃描dao包下dao介面和mapper文件。

    @SpringBootApplication
    @EnableTransactionManagement // 啟用事務管理器,與業務方法上的@Transactional一起使用
    @MapperScan(basePackages = "com.luis.dao") // 指定dao所在的包,掃描dao包下dao介面和mapper文件
    public class SpringbootTransactionalApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootTransactionalApplication.class, args);
        }
    }
    
  10. 運行主啟動類,瀏覽器輸入訪問地址;配合業務方法中設置的運行時異常(分別註釋和放開),觀察訪問結果以及資料庫表中數據變化進行測試

    http://localhost:9090/mytrans/addUser?name=luis&age=5
    測試結果:發生運行時異常,進行了事務回滾,數據操作撤銷,但主鍵會自增;無運行時異常,數據添加成功
    結論:該業務方法支持了事務
    

介面架構風格——RESTful

介面的概念

  • 介面: API(Application Programming Interface,應用程式介面)是一些預先定義的介面(如函數、HTTP介面),或指軟體系統不同組成部分銜接的約定。 用來提供應用程式與開發人員基於某軟體或硬體得以訪問的一組常式,而又無需訪問源碼,或理解內部工作機制的細節。

此介面不是指 Java 中介面 Interface,而是一種應用程式介面,指可訪問 servlet,controller 的 url,調用其他程式的函數!

前後端分離

前後端分離的思想:前端從後端剝離,形成一個前端工程,前端只利用Json來和後端進行交互,後端不返回頁面,只返回Json數據。前後端之間完全通過public API約定。

前後端分離(解耦)的核心思想是:前端Html頁面通過Ajax調用後端的RestFul API並使用Json數據進行交互。

註: 【在互聯網架構中,web伺服器:一般指像nginx,apache這類的伺服器,他們一般只能解析靜態資源。應用伺服器:一般指像tomcat,jetty,resin這類的伺服器可以解析動態資源也可以解析靜態資源,但解析靜態資源的能力沒有web伺服器好。】

一般只有Web伺服器才能被外網訪問,應用伺服器只能內網訪問。

————————————————
版權聲明:本文為CSDN博主「山河遠闊」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_37539378/article/details/79956760

前後端分離並非僅僅只是一種開發模式,而是一種架構模式(前後端分離架構)。
千萬不要以為只有在擼代碼的時候把前端和後端分開就是前後端分離了,需要區分前後端項目!
前端項目與後端項目是兩個項目,放在兩個不同的伺服器,需要獨立部署,兩個不同的工程,兩個不同的代碼庫,不同的開發人員。
前後端工程師需要約定交互介面,實現並行開發,開髮結束後需要進行獨立部署,前端通過ajax來調用http請求調用後端的restful api。
前端只需要關註頁面的樣式與動態數據的解析&渲染,而後端專註於具體業務邏輯。
————————————————下麵原文很有閱讀價值!
版權聲明:本文為CSDN博主「山河遠闊」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_37539378/article/details/79956760

REST 介紹

  • REST (英文:Representational State Transfer ,簡稱 REST;中文: 表現層狀態轉移 )

  • 一種互聯網軟體架構設計的風格,但它並不是標準,它只是提出了一組客戶端和伺服器交互時的架構理念和設計原則,基於這種理念和原則設計的介面可以更簡潔,更有層次。

  • 任何的技術都可以實現這種理念,如果

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 2022-10-28 Tomcat (1)含義:Tomcat是一個使用廣泛的JavaWeb伺服器。 (2)官方下載地址: https://tomcat.apache.org/ 使用8.0版本的就OK。 (3)在使用Tomcat之前需要的準備工作: 正確配置JAVA_HOME的環境變數,配置的內容是j ...
  • 本次案例代碼實現思路: 打開考試網站 selenium --> 瀏覽器驅動 --> 操作瀏覽器 <模擬人的行為做操作瀏覽器> 獲取答案 獲取答案網站鏈接 獲取問題以及答案內容 對比題目以及答案 選出正確答案 獲取問題答案選項 和正確的答案進行對比 如果正確答案和選擇答案一致, 那就進行點擊 進行點擊 ...
  • 1:C++的引用,引用和指針的區別? 1:從彙編指令角度上看,引用和指針沒有區別,引用也是通過地址指針的方式訪問指向的記憶體 int &b=a ; 是需要將a的記憶體地址取出並存下來, b=20;(通過引用修改值時,也是先取出指向的地址,然後訪問該地址的值並修改它,和通過指針修改值一樣) 在定義引用的時 ...
  • 解決辦法是 利用 com.alibaba.fastjson.serializer.ObjectSerializer 和 com.alibaba.fastjson.annotation.JSONField 。 ...
  • 1、Python裡面如何拷貝一個對象?(賦值,淺拷貝,深拷貝的區別) 答:賦值(=),就是創建了對象的一個新的引用,修改其中任意一個變數都會影響到另一個。 淺拷貝:創建一個新的對象,但它包含的是對原始對象中包含項的引用(如果用引用的方式修改其中一個對象,另外一個也會修改改變){1,完全切片方法;2, ...
  • BLOG-2 (1)前言: 總結之前所涉及到的知識點、題量、難度等情況 題目集4:知識點:類與對象、字元串方法調用、正則表達式 題量:多 難度:難 題目集5:知識點:類與對象、字元串方法調用、正則表達式 題量:多 難度:難 期中考試:知識點:類設計、繼承與多態、容器類 題量:少 難度:低 (2)設計 ...
  • 4.HTML 4.3HTML基本標簽 4.3.9表格(table)標簽 基本語法: <table border="邊框寬度" cellspacing="空隙大小" cellpadding="填充大小"> </table> 說明: table 是表格標簽,border 設置表格標簽 width 設置表 ...
  • 簡介 觀察者模式是行為型模式的一種,定義了對象間一對多的關係。當對象的狀態發生變化時候,依賴於它的對象會得到通知。 適用場景 類似觸發鉤子事件,可做消息通知、框架底層監聽。 一個對象的改變會導致一個或多個對象發生改變,方便擴展的寫法。 優點 方便擴展,降低耦合,統一觸發規則。當需要新增或者刪除一個觀 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...