您现在的位置是:首页 >技术交流 >Web应用技术(第十六周/持续更新)网站首页技术交流

Web应用技术(第十六周/持续更新)

liukuande 2024-08-26 12:01:03
简介Web应用技术(第十六周/持续更新)

本次联系基于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包方式:

3.SpringBoot+MyBatis(注解方式):

4.基于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:

完善控制器:

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"; // 返回逻辑视图名
    }

}

5.关于

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。