Web应用技术(第十六周/END)

本次练习基于how2j的教程完成对SpringBoot的初步学习。

学习导入:

在学习SpringBoot前,我们已经学习过SSM了,即Spring、SpringMVC、MyBatis,SpringBoot是与Spring对标的,那么我们可以在学习之前向自己提两个问题:

  • 什么是SpringBoot?
  • 它和Spring有什么区别和联系(为什么要学SpringBoot)?

Spring Boot是一个用于创建基于Spring框架的快速应用程序的开源Java开发框架。它提供了开箱即用的配置,使得开发者可以更加专注于应用程序的业务逻辑而不是繁琐的配置工作。它的核心思想是约定优于配置,即根据一些默认约定来自动配置应用程序,从而简化了开发流程。

Spring Boot是Spring框架的扩展和增强,它建立在Spring框架之上并提供了许多方便的功能。以下是Spring Boot和Spring的区别和联系:

区别:

  • 编码风格不同:Spring Boot鼓励使用Java Config而非XML配置来构建应用程序,并且提供了一些简化的注解用于快速创建Bean,从而使得开发流程更加高效。

  • 自动化配置不同:Spring框架需要手动配置大量的组件来启动应用程序,例如Servlet容器、数据库连接等。而Spring Boot则采用约定优于配置的方式,自动配置这些组件,从而减少了繁琐的配置工作。

  • 依赖管理不同:Spring Boot提供了一个基于Maven或Gradle的依赖管理工具,可以方便地添加所需的各种依赖库,并自动处理版本冲突问题。

联系:

  • 共享Spring核心功能:Spring Boot建立在Spring框架的核心组件之上,包括IoC容器、AOP、数据访问、Web、测试等。因此,Spring Boot应用程序可以像普通的Spring应用程序一样使用这些核心组件。

  • Spring Boot应用程序可以使用Spring框架的所有扩展:Spring Boot应用程序可以使用Spring框架中的所有扩展,例如Spring Security、Spring Data等。

下面是一个简单的示例代码,演示了如何在Spring Boot中创建一个Web应用程序,并使用Spring框架中的IoC容器来管理Bean:

@RestController // 声明这是一个RESTful API控制器
@SpringBootApplication // 标记这是一个Spring Boot应用程序
public class MyApplication {

    @Autowired
    private MyService myService; // 使用@Autowired注解自动装配MyService Bean

    @GetMapping("/") // 处理HTTP GET请求的路由
    public String home() {
        return "Hello, " + myService.getMessage(); // 返回"Hello, World!"
    }

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args); // 启动Spring Boot应用程序
    }
}

@Service // 标记这是一个Spring管理的Bean
public class MyService {

    public String getMessage() {
        return "World!"; // 返回字符串"World!"
    }
}

在上面的代码中,@RestController和@GetMapping注解是Spring Boot的特有标记,用于创建RESTful API。而@Autowired和@Service注解则是Spring框架的核心组件,用于IoC容器的依赖注入和Bean的创建。可以看到,Spring Boot和Spring框架是密切相关的,共同构建了现代Java应用程序的基础。

1.第一个基于SpringBoot的项目:

how2j上的项目建设和部署流程很清楚,我不赘述了,下面我提供带有注释的代码,并且附上一些我的个人理解。

(1)application.java:

package com.how2java.springboot;

import org.springframework.boot.SpringApplication; //导入SpringApplication类
import org.springframework.boot.autoconfigure.SpringBootApplication; //导入SpringBootApplication类
import org.springframework.boot.builder.SpringApplicationBuilder; //导入SpringApplicationBuilder类
import org.springframework.boot.web.servlet.ServletComponentScan; //导入ServletComponentScan类
import org.springframework.boot.web.support.SpringBootServletInitializer; //导入SpringBootServletInitializer类

@SpringBootApplication //声明该类为Spring Boot应用程序的入口
@ServletComponentScan //扫描带有@WebServlet、@WebFilter、@WebListener注解的组件
public class Application extends SpringBootServletInitializer { //继承SpringBootServletInitializer类,以支持war包形式的部署

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { //重写configure方法,以支持war包形式的部署
		return application.sources(Application.class); //返回SpringApplicationBuilder对象
	}

	public static void main(String[] args) { //应用程序的入口
		SpringApplication.run(Application.class, args); //启动Spring Boot应用程序
	}
}

该文件中的核心代码:

SpringApplication.run(Application.class, args); //启动Spring Boot应用程序

SpringApplication.run(Application.class, args)是用于启动Spring Boot应用程序的方法,其具体解析如下:

  • SpringApplication是Spring Boot中的一个静态类,提供了各种启动和配置Spring Boot应用程序的方法。

  • run()方法是启动Spring Boot应用程序的入口点。它需要两个参数:主要配置类的Class对象和main方法的args数组。

  • Application.class是主要配置类的Class对象。在Spring Boot应用程序中,我们需要创建一个Java类作为主要配置类,并在其中定义应用程序的配置信息、数据源等组件。在这里,我们将Application类作为主要配置类的Class对象传递给run()方法。

  • args是main方法接收到的命令行参数。通常情况下,我们不需要传递任何参数给run()方法,直接传递空数组即可。

当调用SpringApplication.run(Application.class, args)方法时,Spring Boot会执行以下步骤:

  1. 加载主要配置类,并创建Spring IoC容器。

  2. 自动扫描并注册所有的Bean组件。

  3. 根据配置信息自动装配Bean组件之间的依赖关系。

  4. 启动内嵌的Web服务器(例如Tomcat或Jetty)。

  5. 监听HTTP请求,并将请求分发到相应的控制器进行处理。

(2)HelloController.java:

// 定义了Java包名,即该类所在的包。
package com.how2java.springboot.web;

// 导入了org.springframework.web.bind.annotation.RequestMapping类,用于处理HTTP请求的注解。
// 导入了org.springframework.web.bind.annotation.RestController类,用于声明该类为RESTful风格的控制器。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

// 使用@RestController注解标记该类为RESTful控制器。
@RestController
public class HelloController {

    // 使用@RequestMapping注解标记该方法为处理HTTP请求的方法,其中"/hello"表示请求的URL路径。
    @RequestMapping("/hello")
    // 定义了该方法的具体实现,即返回一个字符串"Hello Spring Boot!"。
    public String hello() {
        return "Springboot测试!";
    }

}

该文件的核心部分——两个注解:

@RestController:

@RestController是一个Spring MVC注解,它用于声明一个类为RESTful风格的控制器。在Spring Boot应用程序中,我们通常使用@RestController来定义RESTful Web服务。

具体来说,@RestController注解告诉Spring MVC框架,该类是一个控制器,并且该控制器的每个方法都会返回一个HTTP响应,而不是一个视图。这意味着,当我们使用@RestController注解标记一个控制器类时,Spring MVC框架会自动将该类的方法返回的数据转换成相应的HTTP响应,并将其发送给客户端。

@RequestMapping:

@RequestMapping是SpringMVC的注解,相信大家已经很熟悉了,简单来说,它的功能就是为当前的控制器打一个标记,以便浏览器通过Tomcat 根据HTTP请求的URL,顺利地找到这个控制器。

(3)pom.xml:

<!-- 定义了Maven项目的POM文件 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 定义了Maven模型的版本号 -->
    <modelVersion>4.0.0</modelVersion>

  <!-- 定义了项目的groupId -->
  <groupId>com.how2java</groupId>
  <!-- 定义了项目的artifactId -->
  <artifactId>springboot</artifactId>
  <!-- 定义了项目的版本号 -->
  <version>0.0.1-SNAPSHOT</version>
  <!-- 定义了项目的名称 -->
  <name>springboot</name>
 	<packaging>war</packaging>
  <!-- 定义了项目的描述 -->
 
  <description>springboot</description>
  
    <!-- 定义了项目的父级依赖,即使用了Spring Boot的starter parent,版本为1.5.9.RELEASE。 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <!-- 定义了项目的依赖,包括spring-boot-starter-web和junit,其中junit的scope为test,表示只在测试时使用。 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>           
        </dependency>
        
	    <dependency>
		      <groupId>junit</groupId>
		      <artifactId>junit</artifactId>
		      <version>3.8.1</version>
		      <scope>test</scope>
	    </dependency>
    </dependencies>

    <!-- 定义了项目的属性,包括Java版本为1.8。 -->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <!-- 定义了项目的构建配置,包括使用Spring Boot的Maven插件进行构建。 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

这个文件定义了Maven工程项目的配置信息及项目的相关依赖。

(4)运行效果:

运行Application.java,访问地址:http://127.0.0.1:8080/hello

在这里插入图片描述

(5)运行流程:

当我们运行第一个文件时,实际上启动了一个SpringBoot应用程序。SpringBoot应用程序会启动一个内嵌的Tomcat服务器并开始监听HTTP请求,将请求分发到相应的控制器进行处理。

在第二个文件中,我们定义了一个RESTful控制器,它包含一个处理HTTP请求的方法,即hello()方法。当我们访问http://127.0.0.1:8080/hello时,Tomcat服务器会将请求路由到该控制器的hello()方法中,并返回该方法的返回值,即Springboot测试!字符串。因此,我们可以在浏览器中看到该字符串的内容。

(6)Vue的路由和Web应用程序的路由:

由于最近打算用Vue来做课设,在Vue的学习过程中也见到了这个名词

Vue.js官方文档中,路由(Router)被定义为管理应用程序中视图之间导航的机制。Vue
Router是Vue.js官方提供的路由管理器,允许我们通过URL路径来定义应用程序的不同视图,并且可以通过路由参数来传递数据。

举个例子,如果我们正在开发一个电子商务网站,我们可能需要在不同的页面中展示不同的商品列表。我们可以使用Vue Router来实现这个功能。首先,我们需要在Vue应用程序中安装Vue Router,并在Vue实例中声明路由器:

import Vue from 'vue'
import VueRouter from 'vue-router'
import ProductList from './components/ProductList.vue'
import ProductDetails from './components/ProductDetails.vue'

Vue.use(VueRouter)

const routes = [
  { path: '/', component: ProductList },
  { path: '/product/:id', component: ProductDetails, props: true }
]

const router = new VueRouter({
  routes
})

在这个例子中,我们定义了两个路由:一个是根路径(‘/’),对应于商品列表页面,另一个是’/product/:id’,对应于商品详情页面。我们还通过props选项将路由参数传递给ProductDetails组件。

然后,在Vue实例中,我们需要将路由器添加到Vue实例中:

new Vue({
  router,
  el: '#app'
})

最后,在模板中,我们可以使用router-link组件来生成链接到不同的路由:

<router-link to="/">Product List</router-link>
<router-link :to="{ name: 'product', params: { id: 1 }}">Product Details</router-link>

在这个例子中,我们使用router-link组件生成两个链接:一个链接到根路径(‘/’),另一个链接到商品详情页面。通过使用路由器和router-link组件,我们可以轻松地实现在Vue应用程序中进行页面导航的功能。


而在Web应用程序中,路由是指将HTTP请求映射到相应的处理程序或控制器的过程。当客户端发送HTTP请求时,服务器会根据请求的URL路径和其他参数选择相应的处理程序或控制器来处理请求,并返回相应的响应。这个过程就是路由。

在Spring Boot应用程序中,路由是通过Spring MVC框架来实现的。当我们定义一个控制器类,并在其中定义一个处理HTTP请求的方法时,我们可以使用Spring MVC的注解来将该方法映射到一个特定的URL路径。例如,在第二个文件中,我们使用了@RequestMapping("/hello")注解将hello()方法映射到/hello路径。当客户端发送一个HTTP GET请求到/hello路径时,Spring MVC框架会自动将该请求路由到hello()方法,并执行该方法的代码。该方法可以返回任何类型的数据,例如字符串、JSON对象等,Spring MVC框架会将该数据转换成相应的HTTP响应,并将其发送给客户端。

2.SpringBoot部署——war包方式:

Tomcat 是一款常用的 Java Web 应用服务器,而 WAR 包是一种 Java Web 应用程序的标准部署格式。通过将 Spring Boot + Maven 项目打包成 WAR 包后,可以方便地将应用程序部署到 Tomcat 或其他支持 WAR 包格式的Web 服务器上,从而实现对应用程序的发布和运行。

在课堂上我成功打包并且运行了,那个时候项目比较简单,只有hello相关程序和配置,现在我尝试打包具备CRUD的整个项目时总是失败,访问时显示

在这里插入图片描述

后面再试试来debug吧。

3.基于SpringBoot的CRUD(注解方式):

理解了前面SSM的CRUD,SpringBoot的CRUD易如反掌!!
SSM的CRUD还没有搞懂的可以看这篇博客Web应用技术(第十五周/END)


(1)实现思路:

实现SpringBoot的CRUD的思想与SSMCRUD的思想是一样的:
我们的crud本质上,也是一种向用户提供的服务,或者说用户的需求。因此为了实现CRUD:

  • 我们需要修改视图,增加相关按钮,以供用户点击

  • 我们需要修改定义服务的接口,以实现接口最终实现功能

  • 我们需要修改DAO(CategoryMapper),以实现与数据库的交互。

  • 我们需要修改控制器,处理用户不同的/更多的请求。

我们这里由于是通过开源的插件来实现分页的因此还必须额外在pom.xml中添加相关依赖,如果是手动分页就没有这个必要了。

由于我们这是一个小型的项目,不需要进行规范化也不需要进行分工合作,因此我们可以不去写接口来强行定义(规范化)我们的程序需要实现哪些服务,这里how2j从简而行了,没有写接口,其实我认为SSM那里的CRUD也是没有必要去先写一个接口的。

(2)具体实现:

具体细节见Web应用技术(第十五周/END),这里只提供代码和注释,不做重复讲解了。

添加按钮:

listCategory.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!-- 导入核心标签库 -->
   
<div align="center"> <!-- HTML页面布局 -->

</div>
 
<div style="width:500px;margin:20px auto;text-align: center"> <!-- HTML页面布局 -->
    <table align='center' border='1' cellspacing='0'> <!-- HTML表格 -->
        <tr> <!-- 表头 -->
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${page.list}" var="c" varStatus="st"> <!-- 使用JSTL的forEach标签循环遍历查询结果,并将结果设置到HTML页面中 -->
            <tr>
                <td>${c.id}</td> <!-- 输出Category对象的id属性 -->
                <td>${c.name}</td> <!-- 输出Category对象的name属性 -->
                <td><a href="editCategory?id=${c.id}">编辑</a></td> <!-- 创建超链接,用于跳转到编辑页面 -->
                <td><a href="deleteCategory?id=${c.id}">删除</a></td> <!-- 创建超链接,用于提交删除请求 -->
            </tr>
        </c:forEach>
         
    </table>
    <br>
    <div>
                <a href="?start=1">[首  页]</a> <!-- 创建分页导航,用于快速跳转到指定页面 -->
            <a href="?start=${page.pageNum-1}">[上一页]</a>
            <a href="?start=${page.pageNum+1}">[下一页]</a>
            <a href="?start=${page.pages}">[末  页]</a>
    </div>
    <br>
    <form action="addCategory" method="post"> <!-- 创建表单,用于提交新增请求 -->
    id:<input name="id"> <br> <!-- 创建输入框,用于输入新增记录的名称属性 -->
     
    name: <input name="name"> <br> <!-- 创建输入框,用于输入新增记录的名称属性 -->
    <button type="submit">提交</button> <!-- 创建提交按钮,用于提交新增请求 -->
     
    </form>
</div>

editCategory.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%> <!-- 设置页面编码,并启用表达式语言 -->

<div style="margin:0px auto; width:500px"> <!-- HTML页面布局 -->

<form action="updateCategory" method="post"> <!-- 创建表单,用于提交更新请求 -->

name: <input name="name" value="${c.name}"> <br> <!-- 创建输入框,用于输入更新记录的名称属性,并设置初始值为原有值,通过EL表达式获取 -->

<input name="id" type="hidden" value="${c.id}"> <!-- 创建隐藏域,用于提交更新记录的id属性,通过EL表达式获取 -->
<button type="submit">提交</button> <!-- 创建提交按钮,用于提交更新请求 -->

</form>
</div>


完善DAO:

package com.how2java.springboot.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import com.how2java.springboot.pojo.Category;

@Mapper // 声明该接口为MyBatis的Mapper接口,需要通过@MapperScan注解扫描到该类
public interface CategoryMapper {

    @Select("select * from category_ ") // 使用@Select注解指定SQL查询语句
    List<Category> findAll(); // 定义findAll()方法,用于查询所有Category对象,并以List集合的形式返回结果集

    @Insert(" insert into category_ ( id,name ) values (#{id},#{name}) ") // 使用@Insert注解指定SQL插入语句
    public int save(Category category); // 定义save()方法,用于新增Category对象,返回值表示影响的行数

    @Delete(" delete from category_ where id= #{id} ") // 使用@Delete注解指定SQL删除语句
    public void delete(int id); // 定义delete()方法,用于删除指定id的Category对象

    @Select("select * from category_ where id= #{id} ") // 使用@Select注解指定SQL查询语句
    public Category get(int id); // 定义get()方法,用于查询指定id的Category对象

    @Update("update category_ set name=#{name} where id=#{id} ") // 使用@Update注解指定SQL更新语句
    public int update(Category category); // 定义update()方法,用于更新Category对象,返回值表示影响的行数

}

完善控制器(含分页插件“PageHelper”详解):

CategoryController.java:

package com.how2java.springboot.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.how2java.springboot.mapper.CategoryMapper;
import com.how2java.springboot.pojo.Category;

@Controller // 声明该类为Spring MVC的Controller类,用于处理HTTP请求和响应。
public class CategoryController {
    @Autowired 
    private CategoryMapper categoryMapper; // 自动注入CategoryMapper对象

    @RequestMapping("/addCategory")
    public String addCategory(Category c) throws Exception {
        categoryMapper.save(c); // 调用CategoryMapper的save()方法保存Category对象
        return "redirect:listCategory"; // 重定向到listCategory请求
    }

    @RequestMapping("/deleteCategory")
    public String deleteCategory(Category c) throws Exception {
        categoryMapper.delete(c.getId()); // 调用CategoryMapper的delete()方法删除指定id的Category对象
        return "redirect:listCategory"; // 重定向到listCategory请求
    }

    @RequestMapping("/updateCategory")
    public String updateCategory(Category c) throws Exception {
        categoryMapper.update(c); // 调用CategoryMapper的update()方法更新Category对象
        return "redirect:listCategory"; // 重定向到listCategory请求
    }

    @RequestMapping("/editCategory")
    public String editCategory(int id, Model m) throws Exception {
        Category c = categoryMapper.get(id); // 调用CategoryMapper的get()方法查询指定id的Category对象
        m.addAttribute("c", c); // 将查询结果设置到Model中作为属性
        return "editCategory"; // 返回逻辑视图名
    }

    @RequestMapping("/listCategory")
    public String listCategory(Model m, @RequestParam(value = "start", defaultValue = "0") int start,
            @RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
        PageHelper.startPage(start, size, "id desc"); // 使用分页插件PageHelper设置分页参数
        List<Category> cs = categoryMapper.findAll(); // 调用CategoryMapper的findAll()方法查询所有Category对象并返回结果集
        PageInfo<Category> page = new PageInfo<>(cs); // 使用PageInfo对结果集进行包装,以支持更多分页信息的获取
        m.addAttribute("page", page); // 将查询结果设置到Model中作为属性
        return "listCategory"; // 返回逻辑视图名
    }

}

在这个控制器中,CUD的路由及其方法是相对比较简单,这里来说一说我对R(查询/分页)路由及其方法的理解:

  @RequestMapping("/listCategory")
    public String listCategory(Model m, 
    		@RequestParam(value = "start", defaultValue = "0") int start,
            @RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
        PageHelper.startPage(start, size, "id asc"); // 使用分页插件PageHelper设置分页参数
        List<Category> cs = categoryMapper.findAll(); // 调用CategoryMapper的findAll()方法查询所有Category对象并返回结果集
        PageInfo<Category> page = new PageInfo<>(cs); // 使用PageInfo对结果集进行包装,以支持更多分页信息的获取
        m.addAttribute("page", page); // 将查询结果设置到Model中作为属性
        return "listCategory"; // 返回逻辑视图名
    }

上述代码中,

PageHelper.startPage(start, size, "id asc");

表示从以size数量的元组为一页的第start页开始,采用按id升序的方式展示到前端页面上。

			@RequestParam(value = "start", defaultValue = "0") int start,
            @RequestParam(value = "size", defaultValue = "5") int size

这段代码声明了参数start和size,并设置了他们的默认值分别为0和5。

List<Category> cs = categoryMapper.findAll(); // 调用CategoryMapper的findAll()方法查询所有Category对象并返回结果集
PageInfo<Category> page = new PageInfo<>(cs); // 使用PageInfo对结果集进行包装,以支持更多分页信息的获取

第一行代码中,我们调用 categoryMapper.findAll() 方法查询数据库中的所有 Category 记录。这个方法可能会返回大量数据,如果直接全部查询出来,就可能会导致内存溢出等问题。因此,在实际应用中,我们通常会将查询结果进行分页,以提高系统性能和用户体验。

在第二行代码中,我们使用 PageInfo 对查询结果进行包装,并将其保存到 page 变量中。PageInfo 是 MyBatis 分页插件 PageHelper 提供的一个分页数据类,可以将查询结果封装成一个带有分页信息的对象。在这里,我们将查询结果 cs 传入 PageInfo 的构造函数中,并通过泛型 指定了查询结果的类型。MyBatis 会根据查询参数和分页设置,自动计算出总页数、当前页码等分页信息,并将其保存在 PageInfo 对象中。

由于我们是使用插件进行分页的,因此我们需要对插件进行配置:
PageHelperConfig.java:

package com.how2java.springboot.config;

import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.github.pagehelper.PageHelper;

@Configuration //该类为配置类
public class PageHelperConfig {

    @Bean //创建一个Bean实例,用于注入PageHelper对象到容器中
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper(); //创建一个PageHelper对象

        Properties p = new Properties(); //创建Properties对象,用于设置PageHelper的属性
        p.setProperty("offsetAsPageNum", "true"); //设置offsetAsPageNum属性为true
        p.setProperty("rowBoundsWithCount", "true"); //设置rowBoundsWithCount属性为true
        p.setProperty("reasonable", "true"); //设置reasonable属性为true

        pageHelper.setProperties(p); //将设置好的属性赋值给PageHelper对象

        return pageHelper; //返回PageHelper对象
    }
}

这份代码我探明的目前只有这份代码本身,@Configuration 和@Bean注解,以及 p.setProperty(“reasonable”, “true”)。

  • 这份代码配合两个注解,实现IOC和DI
  • p.setProperty(“reasonable”, “true”)用于启用合理化策略,处理一些边界情况。例如当页码小于1时,会将页码强制设为1;当页码大于总页数时,会将页码强制设为总页数。这样可以保证查询结果的准确性和用户体验。

其他部分经我测试,在该案例中是可有可无的。

更新:

p.setProperty("rowBoundsWithCount", "true");

这行代码使得在查询结果进行分页时,不一次性查完全部数据,为cpu增加负担,以提高系统性能和用户体验。

运行查看:

运行application.java后,在浏览器中访问http://127.0.0.1:8080/listCatgory
在这里插入图片描述

4.SpringBoot+MyBatis(配置文件方式):

参考how2j的教程可以比较容易地实现。
这里主要讲一讲我对注解方式xml方式的理解(区别和联系):

MyBatis 和 Spring Boot 结合方式主要有两种:使用注解方式和使用 XML 配置文件方式。它们的区别和联系如下:

  1. 区别
  • 注解方式:使用 @MapperScan@Mapper 注解将 MyBatis Mapper 接口和相应的 XML 文件进行关联,使得 Spring Boot 程序能够自动扫描并加载这些 Mapper 接口实现。不需要额外的配置文件,具有简洁的代码结构和易于维护的特点。
  • XML 配置文件方式:手动编写 MyBatis 的 Mapper XML 文件,在其中定义 SQL 映射关系以及查询逻辑等信息。在 Spring Boot 的配置文件中进行相应的配置,例如指定 Mapper 文件的位置、数据源等信息。需要手动编写和维护 XML 文件,但更加灵活,支持自定义 SQL 语句和查询逻辑。
  1. 联系
  • 共同点:无论是注解方式还是 XML 配置文件方式,都可以将 MyBatis 和 Spring Boot 进行无缝集成,实现对数据库的访问和操作。
  • 相互补充:两种方式各有优劣,使用时可以根据项目需求和个人习惯进行选择。在实际项目中,往往会同时使用两种方式,以满足不同场景的需要。例如,可以使用注解方式实现一些简单的 SQL 查询和更新操作,而对于复杂的 SQL 逻辑,则可以使用 XML 配置文件方式进行定义和管理。

SpringBoot出现,便是为了简化配置,从这一点上来说,注解方式是更符合SpringBoot的设计理念的。但就耦合程度而言,注解却是相对紧耦合的。可见,在项目中选择哪种方式,需要考虑项目需求、代码规模、团队习惯等多方面因素,综合评估后做出更为合适的选择。

5.解决“Whitelabel Error Page”问题:

在运行一个接一个的基于SpringBoot的项目后,由于不正确的操作,可能会出现Whitelabel Error Page的报错提示

在这里插入图片描述

这是由于端口被占用导致的

在这里插入图片描述

上面是一个活动连接列表,在cmd中输入netstat可查询,每一列的意思如下:

  • 协议:连接使用的协议,如TCP或UDP。
  • 本地地址:本地计算机的IP地址和端口号。
  • 外部地址:连接到的远程计算机的IP地址和端口号。
  • 状态:连接的当前状态,如ESTABLISHED表示连接已经建立,TIME_WAIT表示连接已经关闭但是仍在等待一些数据包。

解决方法:
(1)方式一:
每一次启动一个配备内置Tomcat的Java程序前,手动关闭,上一个应用程序,使它不再占用端口

在这里插入图片描述

(2)方式二:
重启Eclipse即可。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值