Java Spring Boot 框架入门教程 — 企业级开发首选

前置要求:Java基础、Maven基础、SQL基础
学习时长:约5-7天(每天4小时)
Spring Boot版本:3.2+
适用场景:企业级应用、微服务、REST API、后台管理系统

一、Spring Boot 是什么?

Spring Boot 是 Java 生态中最流行的Web框架,简化了Spring应用的开发,是企业级Java开发的事实标准。

特点说明
核心理念约定优于配置,开箱即用
学习曲线★★★☆☆(需要Java和Spring基础)
核心优势自动配置、内嵌服务器、Starter依赖
生态完善Spring全家桶:Security、Data、Cloud
就业市场Java岗位中Spring Boot需求占比最高

二、快速开始

2.1 创建项目

# 方式1:使用Spring Initializr(推荐)
# https://start.spring.io/
# 选择:Java 17, Maven, Spring Web, Spring Data JPA, MySQL Driver

# 方式2:命令行
curl https://start.spring.io/starter.zip \
  -d type=maven-project \
  -d language=java \
  -d bootVersion=3.2.0 \
  -d baseDir=myproject \
  -d groupId=com.example \
  -d artifactId=myproject \
  -d dependencies=web,jpa,mysql,lombok \
  -o myproject.zip

unzip myproject.zip
cd myproject

2.2 项目结构

myproject/
├── pom.xml                      # Maven配置
├── src/main/java/com/example/
│   ├── MyprojectApplication.java # 启动类
│   ├── controller/               # 控制器
│   ├── service/                  # 业务逻辑
│   ├── repository/               # 数据访问
│   ├── model/                    # 实体类
│   ├── dto/                      # 数据传输对象
│   ├── config/                   # 配置类
│   └── exception/                # 异常处理
└── src/main/resources/
    ├── application.yml           # 配置文件
    ├── static/                   # 静态资源
    └── templates/                # 模板文件

2.3 配置文件

# application.yml
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8mb4
    username: root
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver
  
  jpa:
    hibernate:
      ddl-auto: update  # 自动更新表结构
    show-sql: true       # 显示SQL
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.MySQLDialect

# 日志配置
logging:
  level:
    com.example: DEBUG
    org.hibernate.SQL: DEBUG


三、核心概念

3.1 启动类

package com.example;

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

@SpringBootApplication  // 组合注解:@Configuration + @EnableAutoConfiguration + @ComponentScan
public class MyprojectApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyprojectApplication.class, args);
    }
}

3.2 控制器(Controller)

package com.example.controller;

import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController  // @Controller + @ResponseBody
@RequestMapping("/api/users")
@CrossOrigin  // 允许跨域
public class UserController {
    
    @Autowired
    private UserService userService;
    
    // GET /api/users
    @GetMapping
    public List<User> getAll() {
        return userService.findAll();
    }
    
    // GET /api/users/1
    @GetMapping("/{id}")
    public ResponseEntity<User> getById(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
    
    // POST /api/users
    @PostMapping
    public ResponseEntity<User> create(@RequestBody User user) {
        User saved = userService.save(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(saved);
    }
    
    // PUT /api/users/1
    @PutMapping("/{id}")
    public ResponseEntity<User> update(@PathVariable Long id, @RequestBody User user) {
        return userService.findById(id)
            .map(existing -> {
                user.setId(id);
                return ResponseEntity.ok(userService.save(user));
            })
            .orElse(ResponseEntity.notFound().build());
    }
    
    // DELETE /api/users/1
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable Long id) {
        if (userService.findById(id).isPresent()) {
            userService.delete(id);
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }
    
    // GET /api/users/search?keyword=张三
    @GetMapping("/search")
    public List<User> search(@RequestParam String keyword) {
        return userService.search(keyword);
    }
}

3.3 实体类(Model)

package com.example.model;

import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(nullable = false, unique = true, length = 100)
    private String email;
    
    @Column(nullable = false)
    private String password;
    
    @Column(length = 20)
    private String phone;
    
    @Column(nullable = false)
    @Builder.Default
    private Boolean isActive = true;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

3.4 数据访问层(Repository)

package com.example.repository;

import com.example.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

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

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    // 方法名查询(Spring Data JPA自动生成SQL)
    Optional<User> findByUsername(String username);
    Optional<User> findByEmail(String email);
    List<User> findByIsActiveTrue();
    List<User> findByUsernameContainingOrEmailContaining(String username, String email);
    
    // 自定义JPQL查询
    @Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.email LIKE %:keyword%")
    List<User> searchByKeyword(@Param("keyword") String keyword);
    
    // 原生SQL查询
    @Query(value = "SELECT * FROM users WHERE is_active = true ORDER BY created_at DESC", nativeQuery = true)
    List<User> findActiveUsers();
    
    // 统计
    long countByIsActiveTrue();
    boolean existsByUsername(String username);
    boolean existsByEmail(String email);
}

3.5 业务逻辑层(Service)

package com.example.service;

import com.example.model.User;
import com.example.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional  // 事务管理
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public List<User> findAll() {
        return userRepository.findAll();
    }
    
    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }
    
    public Optional<User> findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
    
    public User save(User user) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        return userRepository.save(user);
    }
    
    public User update(Long id, User userDetails) {
        User user = userRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        user.setUsername(userDetails.getUsername());
        user.setEmail(userDetails.getEmail());
        user.setPhone(userDetails.getPhone());
        
        return userRepository.save(user);
    }
    
    public void delete(Long id) {
        if (!userRepository.existsById(id)) {
            throw new RuntimeException("用户不存在");
        }
        userRepository.deleteById(id);
    }
    
    public List<User> search(String keyword) {
        return userRepository.searchByKeyword(keyword);
    }
    
    public long countActiveUsers() {
        return userRepository.countByIsActiveTrue();
    }
}


四、请求参数处理

@RestController
@RequestMapping("/api/demo")
public class DemoController {
    
    // 路径参数
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id).orElse(null);
    }
    
    // 查询参数
    @GetMapping("/users")
    public List<User> getUsers(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String keyword) {
        return userService.findWithPagination(page, size, keyword);
    }
    
    // 请求体(JSON)
    @PostMapping("/users")
    public User createUser(@RequestBody @Valid UserDTO userDTO) {
        return userService.createFromDTO(userDTO);
    }
    
    // 表单参数
    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password) {
        return userService.login(username, password);
    }
    
    // 文件上传
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) {
        // 处理文件
        return "上传成功";
    }
    
    // 请求头
    @GetMapping("/info")
    public String getInfo(@RequestHeader("Authorization") String token) {
        return "Token: " + token;
    }
}


五、DTO与参数验证

// DTO(数据传输对象)
package com.example.dto;

import jakarta.validation.constraints.*;
import lombok.Data;

@Data
public class UserDTO {
    
    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 50, message = "用户名长度3-50")
    private String username;
    
    @NotBlank(message = "邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @NotBlank(message = "密码不能为空")
    @Size(min = 6, max = 100, message = "密码长度6-100")
    private String password;
    
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;
}

// 全局异常处理
package com.example.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidation(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String field = ((FieldError) error).getField();
            String message = error.getDefaultMessage();
            errors.put(field, message);
        });
        return ResponseEntity.badRequest().body(errors);
    }
    
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<Map<String, String>> handleRuntime(RuntimeException ex) {
        Map<String, String> error = new HashMap<>();
        error.put("error", ex.getMessage());
        return ResponseEntity.badRequest().body(error);
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, String>> handleGeneral(Exception ex) {
        Map<String, String> error = new HashMap<>();
        error.put("error", "服务器内部错误");
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}


六、分页与排序

// Controller
@GetMapping("/users/page")
public Page<User> getUsersPage(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size,
        @RequestParam(defaultValue = "id") String sortBy,
        @RequestParam(defaultValue = "desc") String direction) {
    
    Sort sort = direction.equalsIgnoreCase("asc") ? 
        Sort.by(sortBy).ascending() : 
        Sort.by(sortBy).descending();
    
    Pageable pageable = PageRequest.of(page, size, sort);
    return userRepository.findAll(pageable);
}

// Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByIsActiveTrue(Pageable pageable);
    Page<User> findByUsernameContaining(String keyword, Pageable pageable);
}

// 返回结果包含
// {
//   "content": [...],
//   "totalElements": 100,
//   "totalPages": 10,
//   "number": 0,        // 当前页
//   "size": 10,         // 每页大小
//   "first": true,
//   "last": false
// }


七、完整项目示例(用户管理系统)

// ====================
// 启动类
// ====================
@SpringBootApplication
public class UserManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserManagementApplication.class, args);
    }
}

// ====================
// 实体类
// ====================
@Entity
@Table(name = "users")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(nullable = false, unique = true, length = 100)
    private String email;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false)
    @Builder.Default
    private Boolean isActive = true;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

// ====================
// Repository
// ====================
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    Optional<User> findByEmail(String email);
    Page<User> findByUsernameContainingOrEmailContaining(
        String username, String email, Pageable pageable);
    long countByIsActiveTrue();
}

// ====================
// Service
// ====================
@Service
@Transactional
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    public Page<User> findAll(int page, int size) {
        return userRepository.findAll(PageRequest.of(page, size, Sort.by("createdAt").descending()));
    }
    
    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }
    
    public User create(UserDTO dto) {
        if (userRepository.existsByUsername(dto.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        if (userRepository.existsByEmail(dto.getEmail())) {
            throw new RuntimeException("邮箱已存在");
        }
        
        User user = User.builder()
            .username(dto.getUsername())
            .email(dto.getEmail())
            .password(passwordEncoder.encode(dto.getPassword()))
            .build();
        
        return userRepository.save(user);
    }
    
    public User update(Long id, UserDTO dto) {
        User user = userRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        user.setUsername(dto.getUsername());
        user.setEmail(dto.getEmail());
        if (dto.getPassword() != null && !dto.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(dto.getPassword()));
        }
        
        return userRepository.save(user);
    }
    
    public void delete(Long id) {
        userRepository.deleteById(id);
    }
    
    public Page<User> search(String keyword, int page, int size) {
        return userRepository.findByUsernameContainingOrEmailContaining(
            keyword, keyword, PageRequest.of(page, size));
    }
}

// ====================
// Controller
// ====================
@RestController
@RequestMapping("/api/users")
@CrossOrigin
public class UserController {
    @Autowired
    private UserService userService;
    
    @GetMapping
    public Page<User> getAll(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return userService.findAll(page, size);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getById(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
    
    @PostMapping
    public ResponseEntity<User> create(@RequestBody @Valid UserDTO dto) {
        return ResponseEntity.status(HttpStatus.CREATED).body(userService.create(dto));
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<User> update(@PathVariable Long id, @RequestBody @Valid UserDTO dto) {
        return ResponseEntity.ok(userService.update(id, dto));
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
    
    @GetMapping("/search")
    public Page<User> search(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return userService.search(keyword, page, size);
    }
}


学习建议

  1. 先理解Spring IoC和DI,这是框架的核心思想
  2. 掌握分层架构:Controller → Service → Repository
  3. 学会使用Lombok,减少样板代码
  4. 理解事务管理,@Transactional是关键
  5. 做一个完整项目,巩固所学知识

下一步学习

返回首页