零基础学Java——第十章:Java Web开发入门(中)- Spring框架和SpringBoot入门

发布于:2025-05-09 ⋅ 阅读:(10) ⋅ 点赞:(0)

第十章:Java Web开发入门(中)- Spring框架和SpringBoot入门

在前面的部分中,我们学习了JSP技术。本部分将介绍Spring框架和SpringBoot,它们是现代Java Web开发中最流行和强大的技术框架,极大地简化了企业级应用的开发。

1. Spring框架入门

1.1 什么是Spring框架

Spring框架是一个开源的Java平台,为开发Java企业级应用提供了全面的基础设施支持。Spring框架的核心特性是依赖注入(DI)和面向切面编程(AOP)。

想象一下,如果你要组装一台电脑,你需要自己找到各种配件(CPU、内存、硬盘等),并将它们正确连接起来。而Spring框架就像一个电脑装配专家,你只需要告诉它你需要什么配件,它会自动帮你找到合适的配件并组装好,让你专注于使用电脑而不是组装电脑。

1.2 Spring框架的核心特性

1.2.1 依赖注入(DI)

依赖注入是Spring最核心的特性,它允许我们将对象之间的依赖关系交给Spring容器管理,而不是在代码中硬编码。

例如,传统方式创建对象:

public class UserService {
    private UserDao userDao = new UserDaoImpl(); // 硬编码依赖
    
    // 业务方法
}

使用Spring依赖注入:

public class UserService {
    private UserDao userDao; // 不直接创建实例
    
    // 通过构造函数注入
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
    
    // 或者通过setter方法注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    
    // 业务方法
}

依赖注入的优势:

  • 降低组件之间的耦合度
  • 更容易进行单元测试
  • 更灵活的配置
1.2.2 面向切面编程(AOP)

AOP允许将横切关注点(如日志记录、事务管理、安全控制)与业务逻辑分离,提高代码的模块化程度。

例如,不使用AOP记录方法执行时间:

public void businessMethod() {
    long startTime = System.currentTimeMillis();
    try {
        // 业务逻辑
        System.out.println("执行业务逻辑");
    } finally {
        long endTime = System.currentTimeMillis();
        System.out.println("方法执行时间:" + (endTime - startTime) + "ms");
    }
}

使用AOP:

// 业务方法 - 只关注业务逻辑
public void businessMethod() {
    System.out.println("执行业务逻辑");
}

// 切面 - 处理横切关注点
@Aspect
public class PerformanceAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature() + " 执行时间:" + (endTime - startTime) + "ms");
        return result;
    }
}

1.3 Spring的核心模块

Spring框架由多个模块组成,主要包括:

  • Spring Core:提供框架的基础功能,包括IoC和DI
  • Spring AOP:提供面向切面编程的实现
  • Spring JDBC:简化JDBC编程
  • Spring ORM:整合主流ORM框架(如Hibernate、JPA)
  • Spring Web:提供Web应用开发的基础功能
  • Spring MVC:实现MVC设计模式的Web框架
  • Spring Security:提供安全框架
  • Spring Data:简化数据访问

1.4 Spring MVC简介

Spring MVC是Spring框架的一个模块,专门用于开发Web应用。它实现了MVC(Model-View-Controller)设计模式,将应用分为模型、视图和控制器三个部分。

1.4.1 Spring MVC的工作流程
  1. 客户端发送请求到DispatcherServlet(前端控制器)
  2. DispatcherServlet根据请求找到对应的Handler(Controller)
  3. Controller处理请求并返回ModelAndView
  4. ViewResolver解析视图名称,找到对应的View
  5. View渲染数据,生成响应
  6. 返回响应给客户端
1.4.2 Spring MVC示例
// 控制器
@Controller
public class HelloController {
    
    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, Spring MVC!");
        return "hello"; // 视图名称
    }
}

对应的视图(hello.jsp):

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Spring MVC示例</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

1.5 Spring配置方式

Spring提供了多种配置方式:

1.5.1 XML配置
<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 定义bean -->
    <bean id="userDao" class="com.example.dao.UserDaoImpl" />
    
    <bean id="userService" class="com.example.service.UserServiceImpl">
        <!-- 注入依赖 -->
        <property name="userDao" ref="userDao" />
    </bean>
</beans>
1.5.2 注解配置
// 配置类
@Configuration
@ComponentScan("com.example")
public class AppConfig {
    
    @Bean
    public UserDao userDao() {
        return new UserDaoImpl();
    }
    
    @Bean
    public UserService userService() {
        return new UserServiceImpl(userDao()); // 构造函数注入
    }
}

组件类:

@Repository
public class UserDaoImpl implements UserDao {
    // 实现方法
}

@Service
public class UserServiceImpl implements UserService {
    private final UserDao userDao;
    
    @Autowired // 自动注入
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    
    // 业务方法
}

2. SpringBoot入门

2.1 什么是SpringBoot

SpringBoot是Spring框架的扩展,它简化了Spring应用的初始搭建和开发过程。SpringBoot采用了"约定优于配置"的原则,大量减少了配置文件的需求。

如果说Spring框架是一套工具箱,那么SpringBoot就是一个已经预装了常用工具的工具箱,你拿到就可以直接使用,不需要自己去组装。

2.2 SpringBoot的主要特性

  • 自动配置:根据项目依赖自动配置Spring应用
  • 起步依赖:简化依赖管理
  • 内嵌服务器:内置Tomcat、Jetty或Undertow,无需部署WAR文件
  • Actuator:提供生产级别的监控和管理功能
  • 无需XML配置:使用Java配置或属性文件

2.3 创建SpringBoot应用

2.3.1 使用Spring Initializr

最简单的方式是使用Spring官方提供的Spring Initializr网站生成项目骨架。

2.3.2 使用IDE插件

主流IDE(如IntelliJ IDEA、Eclipse)都提供了SpringBoot项目创建向导。

2.3.3 使用Maven或Gradle

手动创建Maven项目,添加SpringBoot依赖:

<!-- pom.xml -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

2.4 SpringBoot应用结构

一个典型的SpringBoot应用结构如下:

src
├── main
│   ├── java
│   │   └── com
│   │       └── example
│   │           └── demo
│   │               ├── DemoApplication.java        # 主类
│   │               ├── controller                  # 控制器
│   │               ├── service                     # 服务层
│   │               ├── repository                  # 数据访问层
│   │               └── model                       # 实体类
│   └── resources
│       ├── application.properties                  # 配置文件
│       ├── static                                  # 静态资源
│       └── templates                               # 模板文件
└── test                                            # 测试代码

2.5 SpringBoot核心组件

2.5.1 主类和@SpringBootApplication注解
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication注解是一个组合注解,它包含:

  • @Configuration:标记该类为配置类
  • @EnableAutoConfiguration:启用自动配置
  • @ComponentScan:启用组件扫描
2.5.2 配置文件

SpringBoot支持多种配置方式,最常用的是application.propertiesapplication.yml

# application.properties
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
# application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password
2.5.3 起步依赖

SpringBoot提供了多种起步依赖(Starter),简化依赖管理:

  • spring-boot-starter-web:Web应用开发
  • spring-boot-starter-data-jpa:JPA数据访问
  • spring-boot-starter-security:安全框架
  • spring-boot-starter-test:测试框架
  • spring-boot-starter-thymeleaf:Thymeleaf模板引擎

2.6 SpringBoot实战:RESTful API

下面我们将创建一个简单的图书管理RESTful API。

2.6.1 创建实体类
package com.example.bookstore.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String author;
    private String isbn;
    private double price;
    
    // 构造函数、getter和setter方法
    public Book() {}
    
    public Book(String title, String author, String isbn, double price) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
        this.price = price;
    }
    
    // Getter和Setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }
    
    public String getIsbn() { return isbn; }
    public void setIsbn(String isbn) { this.isbn = isbn; }
    
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
}
2.6.2 创建Repository
package com.example.bookstore.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.bookstore.model.Book;

public interface BookRepository extends JpaRepository<Book, Long> {
    // Spring Data JPA会自动实现基本的CRUD操作
    // 可以添加自定义查询方法
    Book findByIsbn(String isbn);
}
2.6.3 创建Service
package com.example.bookstore.service;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.bookstore.model.Book;
import com.example.bookstore.repository.BookRepository;

@Service
public class BookService {
    private final BookRepository bookRepository;
    
    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
    
    public List<Book> findAllBooks() {
        return bookRepository.findAll();
    }
    
    public Optional<Book> findBookById(Long id) {
        return bookRepository.findById(id);
    }
    
    public Book findBookByIsbn(String isbn) {
        return bookRepository.findByIsbn(isbn);
    }
    
    public Book saveBook(Book book) {
        return bookRepository.save(book);
    }
    
    public void deleteBook(Long id) {
        bookRepository.deleteById(id);
    }
}
2.6.4 创建Controller
package com.example.bookstore.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.example.bookstore.model.Book;
import com.example.bookstore.service.BookService;

@RestController
@RequestMapping("/api/books")
public class BookController {
    private final BookService bookService;
    
    @Autowired
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }
    
    // 获取所有图书
    @GetMapping
    public List<Book> getAllBooks() {
        return bookService.findAllBooks();
    }
    
    // 根据ID获取图书
    @GetMapping("/{id}")
    public ResponseEntity<Book> getBookById(@PathVariable Long id) {
        return bookService.findBookById(id)
                .map(book -> ResponseEntity.ok().body(book))
                .orElse(ResponseEntity.notFound().build());
    }
    
    // 创建新图书
    @PostMapping
    public ResponseEntity<Book> createBook(@RequestBody Book book) {
        Book savedBook = bookService.saveBook(book);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedBook);
    }
    
    // 更新图书
    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBook(@PathVariable Long id, @RequestBody Book book) {
        return bookService.findBookById(id)
                .map(existingBook -> {
                    existingBook.setTitle(book.getTitle());
                    existingBook.setAuthor(book.getAuthor());
                    existingBook.setIsbn(book.getIsbn());
                    existingBook.setPrice(book.getPrice());
                    Book updatedBook = bookService.saveBook(existingBook);
                    return ResponseEntity.ok().body(updatedBook);
                })
                .orElse(ResponseEntity.notFound().build());
    }
    
    // 删除图书
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
        return bookService.findBookById(id)
                .map(book -> {
                    bookService.deleteBook(id);
                    return ResponseEntity.noContent().<Void>build();
                })
                .orElse(ResponseEntity.notFound().build());
    }
}
2.6.5 配置文件
# application.properties
server.port=8080

# 数据库配置
spring.datasource.url=jdbc:h2:mem:bookstore
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# JPA配置
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update

# H2控制台
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
2.6.6 主类
package com.example.bookstore;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

2.7 SpringBoot的高级特性

2.7.1 配置文件属性注入
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private String description;
    private int version;
    
    // Getter和Setter
}

对应的配置:

app.name=我的应用
app.description=这是一个示例应用
app.version=1
2.7.2 条件注解

SpringBoot提供了多种条件注解,用于根据条件创建Bean:

@Configuration
public class DatabaseConfig {
    
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "mysql")
    public DataSource mysqlDataSource() {
        // 创建MySQL数据源
    }
    
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "h2")
    public DataSource h2DataSource() {
        // 创建H2数据源
    }
}
2.7.3 自定义启动器

可以创建自己的SpringBoot启动器,封装特定功能:

  1. 创建自动配置类
  2. 创建配置属性类
  3. 注册自动配置类
  4. 创建启动器模块

总结

在本章中,我们学习了Spring框架和SpringBoot的基础知识。Spring框架通过依赖注入和面向切面编程简化了Java企业级应用的开发,而SpringBoot则进一步简化了Spring应用的配置和部署。

我们了解了Spring的核心特性、主要模块和配置方式,以及SpringBoot的特性、应用结构和核心组件。通过一个图书管理RESTful API的实例,我们实践了SpringBoot的使用。

这些技术在现代Java Web开发中扮演着重要角色,掌握它们将使你能够更高效地开发企业级应用。

在下一部分,我们将学习RESTful API设计和前后端分离开发,这是现代Web应用开发的重要趋势。


网站公告

今日签到

点亮在社区的每一天
去签到