Web 后端开发
难度等级:⭐⭐⭐ 前置知识:编程语言基础 后续衔接:微服务架构、数据存储
学习路径
- 入门阶段:掌握一个框架的路由、请求处理、响应
- 进阶阶段:理解 ORM、中间件、安全认证
- 精通阶段:能够进行高并发后端架构设计
一、.NET Web 开发
1.1 ASP.NET Core 基础
ASP.NET Core 是微软推出的跨平台、高性能 Web 框架,采用模块化设计,运行于 .NET 运行时之上。其核心架构围绕中间件管道、依赖注入、配置系统三大支柱展开。
中间件管道是 ASP.NET Core 请求处理的核心机制。每个中间件组件负责处理 HTTP 请求和响应,它们按注册顺序串联成管道。请求从第一个中间件流入,依次传递,响应则反向流出。中间件通过 app.Use() 注册,短路中间件(如 app.Run())会终止管道。典型管道顺序为:异常处理 → HTTPS 重定向 → 静态文件 → 路由 → 认证 → 授权 → 端点。理解管道顺序至关重要,错误的顺序会导致认证在授权之前未执行等问题。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 中间件管道(顺序重要)
app.UseExceptionHandler("/error");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
依赖注入(DI)是 ASP.NET Core 的一等公民。框架内置轻量级 DI 容器,支持三种生命周期:Transient(每次请求创建新实例)、Scoped(同一请求内共享)、Singleton(应用生命周期内唯一)。服务在 Program.cs 中注册,通过构造函数注入到控制器。推荐优先使用 Scoped 注册数据库上下文等有状态服务,避免 Singleton 持有可变状态引发的线程安全问题。
配置系统采用 IConfiguration 抽象,支持多数据源叠加:appsettings.json → appsettings.{Environment}.json → 环境变量 → 命令行参数 → 用户机密(开发环境)。配置值通过键路径访问(如 Configuration["ConnectionStrings:Default"]),也可通过 IOptions<T> 强类型绑定,实现配置类的集中管理。
// 强类型配置
builder.Services.Configure<JwtSettings>(
builder.Configuration.GetSection("JwtSettings"));
// 在类中使用
public class AuthService(IOptions<JwtSettings> options)
{
private readonly JwtSettings _settings = options.Value;
}
路由系统支持传统路由和端点路由两种模式。端点路由(推荐)将路由匹配与请求处理分离,允许中间件在路由决策后介入。属性路由通过 [Route]、[HttpGet] 等注解定义,约定路由通过 MapControllerRoute 配置。路由约束(如 {id:int})和路由值模型绑定是构建 RESTful API 的基础。
1.2 Web API 设计
RESTful API 设计是后端开发的核心技能。ASP.NET Core 提供了完整的 Web API 构建能力,涵盖控制器、模型验证、响应格式化、版本管理等环节。
RESTful 设计原则强调资源导向、无状态通信、统一接口。资源通过 URI 标识(如 /api/users/123),HTTP 方法表达操作语义(GET 查询、POST 创建、PUT 全量更新、PATCH 局部更新、DELETE 删除)。状态码准确反映操作结果:200 成功、201 创建成功、204 无内容、400 请求错误、401 未认证、403 无权限、404 未找到、500 服务器错误。避免在 GET 请求中修改资源状态,确保接口的幂等性和安全性。
控制器是 API 端点的载体,继承 ControllerBase(非 Controller,后者包含视图支持)。使用 [ApiController] 特性可启用自动模型验证、多部分表单绑定推断、绑定源参数推断等增强行为。推荐将控制器保持轻薄,仅负责请求参数接收、服务调用和响应返回,业务逻辑下沉到服务层。
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> GetUser(int id)
{
var user = await _userService.GetByIdAsync(id);
if (user == null)
return NotFound();
return Ok(user);
}
[HttpPost]
public async Task<ActionResult<UserDto>> CreateUser(CreateUserRequest request)
{
var user = await _userService.CreateAsync(request);
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}
}
模型验证通过 Data Annotations 实现,[Required]、[StringLength]、[Range]、[EmailAddress] 等特性标注在 DTO 属性上。[ApiController] 会自动在动作执行前检查 ModelState.IsValid,验证失败时返回 400 响应。对于复杂验证逻辑,可实现 IValidatableObject 接口或使用 FluentValidation 库,后者支持链式语法和异步验证,更适合企业级项目。
public class CreateUserRequest
{
[Required]
[StringLength(50, MinimumLength = 2)]
public string Name { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Range(18, 120)]
public int Age { get; set; }
}
响应格式化通过内容协商实现,客户端通过 Accept 头指定期望格式,服务端通过 OutputFormatter 匹配。默认支持 JSON 和 XML,推荐仅启用 JSON 以减少攻击面。全局异常处理通过中间件实现,捕获未处理异常后返回统一的错误响应格式,避免泄露堆栈信息。
1.3 Entity Framework Core
Entity Framework Core(EF Core)是 .NET 生态的官方 ORM 框架,支持 Code First、Database First 和 Model First 三种开发模式,其中 Code First 最为常用。
Code First 模式通过 C# 实体类定义数据模型,利用 Fluent API 或 Data Annotations 配置映射关系。数据库上下文 DbContext 是 EF Core 的核心类,管理实体集合和数据库连接。DbSet<T> 表示数据库表的集合,支持 LINQ 查询。迁移(Migration)机制用于管理数据库架构变更,通过 dotnet ef migrations add 生成迁移文件,dotnet ef database update 应用到数据库。迁移文件包含 Up 和 Down 方法,支持正向升级和回滚。
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<User> Users { get; set; }
public DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Email).IsRequired().HasMaxLength(100);
entity.HasIndex(e => e.Email).IsUnique();
entity.HasMany(e => e.Orders)
.WithOne(e => e.User)
.HasForeignKey(e => e.UserId);
});
}
}
LINQ 查询是 EF Core 的数据访问语言。Where、Select、OrderBy、Include、ThenInclude 等方法构建查询表达式树,最终翻译为 SQL 执行。Include 用于加载关联实体(eager loading),避免 N+1 查询问题。AsNoTracking() 用于只读查询,跳过变更跟踪以提升性能。Select 投影仅查询需要的字段,减少数据传输量。
// 高效查询示例
var users = await _context.Users
.AsNoTracking()
.Where(u => u.IsActive && u.CreatedAt > DateTime.UtcNow.AddDays(-30))
.Select(u => new { u.Id, u.Name, u.Email })
.OrderByDescending(u => u.Id)
.Skip(0)
.Take(20)
.ToListAsync();
性能优化是 EF Core 实战的关键。常见问题包括:N+1 查询(通过 Include 或显式加载解决)、变更跟踪开销(只读查询使用 AsNoTracking)、内存中数据膨胀(使用 Select 投影)、批量操作性能(使用 AddRange/ExecuteUpdateAsync 而非循环 Add)。EF Core 7+ 引入了 ExecuteUpdateAsync 和 ExecuteDeleteAsync 用于批量更新和删除,直接在数据库执行而不加载实体到内存。对于超高并发场景,可考虑 Dapper 等轻量级 ORM 作为补充。
// EF Core 7+ 批量更新
await _context.Users
.Where(u => u.LastLoginAt < DateTime.UtcNow.AddYears(-1))
.ExecuteUpdateAsync(u => u.SetProperty(x => x.IsActive, false));
二、Java / Spring Boot 开发
2.1 Spring 核心原理
Spring 框架是 Java 生态中最具影响力的企业级开发框架,其核心是 IoC(控制反转)容器和 AOP(面向切面编程) 两大机制。
IoC 容器负责管理对象的生命周期和依赖关系。传统开发中,对象自行创建依赖(new 关键字),导致紧耦合。IoC 将依赖创建和注入的责任交给容器,对象只需声明依赖,容器在运行时自动注入。Spring 通过 BeanFactory 和 ApplicationContext 实现 IoC,前者是基础容器,后者提供国际化、事件传播等企业级功能。Bean 是容器管理的对象,通过 XML、注解或 Java Config 定义。推荐使用 @Configuration + @Bean 或 @Component 系列注解的 Java Config 方式,类型安全且易于重构。
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
return new HikariDataSource();
}
@Bean
public UserService userService(DataSource dataSource) {
return new UserServiceImpl(dataSource);
}
}
Bean 生命周期包含多个阶段:实例化 → 属性注入 → 初始化前(BeanPostProcessor.postProcessBeforeInitialization)→ 初始化(@PostConstruct、InitializingBean.afterPropertiesSet、自定义 init-method)→ 初始化后(BeanPostProcessor.postProcessAfterInitialization)→ 使用 → 销毁(@PreDestroy、DisposableBean.destroy)。理解生命周期对于编写自定义 Bean 处理器和代理至关重要。
AOP 切面编程将横切关注点(日志、事务、安全)与业务逻辑分离。核心概念包括:切面(Aspect,横切逻辑的模块化)、连接点(JoinPoint,程序执行点,如方法调用)、通知(Advice,在连接点执行的动作,分 Before/After/AfterReturning/AfterThrowing/Around)、切点(Pointcut,匹配连接点的表达式)。Spring AOP 基于动态代理实现,默认使用 JDK 动态代理(面向接口)或 CGLIB(面向类)。@Aspect 注解定义切面,@Pointcut 定义切点表达式,@Before/@After 等定义通知。
@Aspect
@Component
public class LoggingAspect {
@Pointcut("execution(* com.example.service..*(..))")
public void serviceMethods() {}
@Around("serviceMethods()")
public Object logExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long elapsed = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature() + " 执行耗时: " + elapsed + "ms");
return result;
}
}
2.2 Spring Boot 自动配置
Spring Boot 的核心价值在于约定优于配置,通过自动配置机制极大简化了 Spring 应用的初始搭建和配置工作。
Starter 机制是一组依赖描述符,将常用场景的依赖打包为一个 Starter POM。例如 spring-boot-starter-web 自动引入 Spring MVC、Tomcat、Jackson 等依赖。Starter 命名遵循 spring-boot-starter-{name} 规范,第三方 Starter 使用 {name}-spring-boot-starter。通过 Starter,开发者只需引入一个依赖即可获得完整的场景支持。
自动配置(Auto-Configuration) 是 Spring Boot 的核心魔法。@EnableAutoConfiguration 注解触发 spring.factories(Spring Boot 3.x 改为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)中声明的自动配置类。每个自动配置类通过 @Conditional 系列注解判断是否生效,例如 @ConditionalOnClass(类路径存在某类时生效)、@ConditionalOnMissingBean(容器中不存在某 Bean 时生效)、@ConditionalOnProperty(配置属性满足条件时生效)。
// 简化的自动配置类示例
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DataSourceProperties properties) {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(properties.getUrl());
ds.setUsername(properties.getUsername());
ds.setPassword(properties.getPassword());
return ds;
}
}
条件注解的优先级决定了自动配置的覆盖顺序。用户自定义的 @Bean 优先级最高(因为 @ConditionalOnMissingBean 会跳过),其次是 @Configuration 类中的 Bean,最后是自动配置类中的 Bean。这种设计允许开发者通过自定义 Bean 轻松覆盖默认配置。spring-boot-autoconfigure 源码是学习 Spring Boot 设计思想的最佳材料。
外部化配置支持 YAML、Properties、环境变量、命令行参数等多种格式,按优先级叠加:命令行参数 > Java 系统属性 > 操作系统环境变量 > application-{profile}.yml > application.yml。@Value 注解注入单个属性值,@ConfigurationProperties 批量绑定到 POJO,后者支持 JSR-303 校验和元数据提示,是推荐做法。
@ConfigurationProperties(prefix = "app.security")
@Validated
public class SecurityProperties {
@NotBlank
private String jwtSecret;
private long tokenExpiration = 3600;
private List<String> allowedOrigins = List.of("*");
}
2.3 Spring MVC
Spring MVC 是 Spring 的 Web 模块,基于前端控制器模式构建,所有请求统一经过 DispatcherServlet 分发处理。
DispatcherServlet 是 Spring MVC 的核心中枢,负责请求的统一分发。处理流程为:接收请求 → HandlerMapping 查找匹配的处理器 → HandlerAdapter 执行处理器 → 处理器返回 ModelAndView → ViewResolver 解析视图 → 渲染响应。在 RESTful API 场景中,处理器直接返回数据对象(标注 @RestController),跳过视图解析环节,由 HttpMessageConverter 将对象序列化为 JSON。
拦截器(Interceptor) 在请求到达控制器前后执行,实现横切逻辑。实现 HandlerInterceptor 接口,重写 preHandle(控制器前)、postHandle(控制器后、视图渲染前)、afterCompletion(请求完成后)方法。拦截器适用于日志记录、性能监控、权限校验等场景。与 Filter 的区别在于:Filter 属于 Servlet 规范,在 DispatcherServlet 之前执行;拦截器属于 Spring MVC,在 DispatcherServlet 内部执行,可访问 Spring 容器中的 Bean。
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
return true;
}
}
异常处理通过 @ControllerAdvice + @ExceptionHandler 实现全局统一处理。标注 @ControllerAdvice 的类可拦截所有控制器抛出的异常,@ExceptionHandler 方法针对特定异常类型返回自定义响应。结合 @ResponseStatus 可设置 HTTP 状态码。推荐定义统一的错误响应结构(包含错误码、消息、详情),便于前端统一处理。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
return new ErrorResponse("NOT_FOUND", ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return new ErrorResponse("VALIDATION_ERROR", message);
}
}
参数绑定将 HTTP 请求数据映射到控制器方法参数。@RequestParam 绑定查询参数,@PathVariable 绑定路径变量,@RequestBody 绑定请求体(自动反序列化),@RequestHeader 绑定请求头。@Valid 或 @Validated 触发 JSR-303 校验,校验失败抛出 MethodArgumentNotValidException。Spring Boot 3.x 从 javax.validation 迁移到 jakarta.validation,注意包名变更。
2.4 Spring Data JPA
Spring Data JPA 是 Spring 对 JPA(Java Persistence API)的抽象封装,通过约定优于配置的理念极大简化了数据访问层的开发。
Repository 抽象是 Spring Data 的核心。定义接口继承 JpaRepository<T, ID> 即可自动获得 CRUD、分页、排序等基础方法,无需编写实现类。Spring 在运行时通过动态代理生成实现。CrudRepository 提供基础 CRUD,PagingAndSortingRepository 增加分页和排序,JpaRepository 在此基础上增加批量操作和 JPA 特有功能。
public interface UserRepository extends JpaRepository<User, Long> {
// 方法名派生查询
Optional<User> findByEmail(String email);
List<User> findByStatusAndCreatedAtAfter(String status, LocalDateTime date);
boolean existsByUsername(String username);
// JPQL 查询
@Query("SELECT u FROM User u WHERE u.email LIKE %:keyword%")
List<User> searchByEmail(@Param("keyword") String keyword);
// 原生 SQL
@Query(value = "SELECT * FROM users WHERE status = ?1", nativeQuery = true)
List<User> findByStatusNative(String status);
// 更新操作
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
int updateStatus(@Param("id") Long id, @Param("status") String status);
}
查询方法派生通过方法名自动解析查询逻辑。findBy、readBy、getBy 为前缀,后接属性名和关键字(And、Or、Between、LessThan、Like、OrderBy 等)。Spring 解析方法名生成对应的 JPQL 查询。这种方式适合简单查询,复杂查询仍需 @Query 注解。
分页与排序通过 Pageable 和 Sort 参数实现。PageRequest.of(page, size, Sort.by("createdAt").descending()) 构建分页排序对象。返回类型使用 Page<T> 可获取总记录数、总页数等元数据,使用 List<T> 或 Slice<T> 则仅返回当前页数据。
// 分页查询
Page<User> page = userRepository.findAll(
PageRequest.of(0, 20, Sort.by("createdAt").descending()));
List<User> content = page.getContent();
long totalElements = page.getTotalElements();
int totalPages = page.getTotalPages();
实体关系映射通过 @OneToOne、@OneToMany、@ManyToOne、@ManyToMany 定义。注意懒加载(FetchType.LAZY)与急加载(FetchType.EAGER)的选择,默认 @OneToMany 为懒加载,@ManyToOne 为急加载。懒加载在访问关联属性时触发额外查询,可能导致 N+1 问题。使用 @EntityGraph 或 JPQL JOIN FETCH 可一次性加载关联数据。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;
}
2.5 MyBatis
MyBatis 是半自动 ORM 框架,将 SQL 控制权完全交给开发者,通过 XML 映射文件或注解将 SQL 结果映射到 Java 对象。在复杂查询、性能调优、遗留数据库适配等场景中,MyBatis 比 JPA 更具灵活性。
XML 映射是 MyBatis 的核心用法。每个 Mapper 接口对应一个 XML 文件,namespace 指向接口的全限定名。<select>、<insert>、<update>、<delete> 标签定义 SQL 语句,id 对应接口方法名,resultType 或 resultMap 指定结果映射。#{} 是预编译参数占位符(防 SQL 注入),${} 是字符串替换(用于动态表名、列名,需注意注入风险)。
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<association property="department" javaType="Department">
<id property="id" column="dept_id"/>
<result property="name" column="dept_name"/>
</association>
</resultMap>
<select id="findById" resultMap="userResultMap">
SELECT u.*, d.id AS dept_id, d.name AS dept_name
FROM users u
LEFT JOIN departments d ON u.department_id = d.id
WHERE u.id = #{id}
</select>
<select id="search" resultMap="userResultMap">
SELECT * FROM users
<where>
<if test="keyword != null">
AND (username LIKE CONCAT('%', #{keyword}, '%')
OR email LIKE CONCAT('%', #{keyword}, '%'))
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
ORDER BY created_at DESC
LIMIT #{offset}, #{limit}
</select>
</mapper>
动态 SQL 是 MyBatis 的亮点。<if> 条件判断、<choose>/<when>/<otherwise> 多分支选择、<foreach> 集合遍历、<where> 智能拼接 WHERE 子句(自动去除多余 AND/OR)、<set> 智能拼接 SET 子句(自动去除多余逗号)、<trim> 自定义前后缀和覆盖。这些标签使 SQL 可根据参数动态生成,避免编写大量重复的 SQL 变体。
插件机制通过实现 Interceptor 接口拦截 MyBatis 内部方法执行。典型应用包括:分页插件(如 PageHelper 拦截 SQL 添加 LIMIT)、SQL 性能监控插件(记录慢查询)、数据权限插件(自动追加 WHERE 条件)。插件通过 @Intercepts 和 @Signature 注解声明拦截点,可拦截 Executor、ParameterHandler、ResultSetHandler、StatementHandler 四个核心组件。
@Intercepts({
@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class})
})
public class SqlTimerInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = invocation.proceed();
long elapsed = System.currentTimeMillis() - start;
if (elapsed > 1000) {
log.warn("慢查询: {}ms", elapsed);
}
return result;
}
}
MyBatis-Plus 是 MyBatis 的增强工具,在保持 MyBatis 灵活性的同时提供了类似 Spring Data JPA 的 CRUD 抽象。BaseMapper<T> 提供基础 CRUD,IService<T> 提供业务层封装,Wrappers 提供链式查询构建器。代码生成器可根据数据库表自动生成实体类、Mapper、Service、Controller 代码,大幅提升开发效率。
2.6 Spring Security
Spring Security 是 Spring 生态的认证与授权框架,功能强大但学习曲线较陡。其核心模型围绕认证(Authentication)和授权(Authorization)展开。
认证流程基于 AuthenticationManager → AuthenticationProvider → UserDetailsService 的链路。AuthenticationManager 是认证入口,委托给 AuthenticationProvider 执行具体认证逻辑。DaoAuthenticationProvider 是最常用的 Provider,通过 UserDetailsService.loadUserByUsername() 加载用户信息,比对密码。认证成功生成包含用户信息和权限的 Authentication 对象,存入 SecurityContextHolder(默认基于 ThreadLocal)。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthFilter,
UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
授权模型基于角色(Role)和权限(Authority)。hasRole() 检查角色(自动添加 ROLE_ 前缀),hasAuthority() 检查具体权限,hasAnyRole()/hasAnyAuthority() 检查多个。方法级安全通过 @EnableMethodSecurity 启用,支持 @PreAuthorize(方法执行前校验)、@PostAuthorize(方法执行后校验)、@PreFilter/@PostFilter(集合过滤)。
JWT 集成是无状态认证的常见方案。JWT(JSON Web Token)包含 Header、Payload、Signature 三部分,服务端签发后客户端存储在请求头中。自定义 Filter 拦截请求,提取并验证 Token,构建 Authentication 对象存入 SecurityContext。注意 JWT 无法主动失效,需配合短有效期 + Refresh Token 或 Token 黑名单机制。
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String token = extractToken(request);
if (token != null && jwtUtil.validateToken(token)) {
String username = jwtUtil.getUsername(token);
Authentication auth = new UsernamePasswordAuthenticationToken(
username, null, jwtUtil.getAuthorities(token));
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
}
OAuth2 是第三方授权的标准协议。Spring Security OAuth2 支持 Authorization Server(颁发 Token)和 Resource Server(验证 Token)两种角色。Resource Server 配置通过 oauth2ResourceServer() 实现,自动验证 JWT 签名并提取权限信息。
2.7 事务管理
事务是保证数据一致性的核心机制。Spring 通过 @Transactional 注解提供声明式事务管理,基于 AOP 代理实现。
@Transactional 工作原理:标注该注解的方法被调用时,Spring 在方法执行前开启事务,正常返回时提交事务,抛出异常时回滚事务。默认仅对 RuntimeException 和 Error 回滚,检查型异常(Checked Exception)不回滚,可通过 rollbackFor 属性修改。事务通过 AOP 代理实现,同类内部方法调用不会触发事务(因为绕过了代理),需通过注入自身或 AopContext.currentProxy() 解决。
@Service
public class OrderService {
@Transactional
public Order createOrder(OrderRequest request) {
Order order = orderRepository.save(request.toEntity());
// 扣减库存
inventoryService.deduct(request.getItems());
// 发送通知
notificationService.send(order);
return order;
}
@Transactional(readOnly = true)
public List<Order> getOrders(Long userId) {
return orderRepository.findByUserId(userId);
}
}
传播行为(Propagation) 定义方法被另一个事务方法调用时的事务行为。REQUIRED(默认):加入现有事务,不存在则新建;REQUIRES_NEW:挂起现有事务,新建独立事务;NESTED:嵌套事务(保存点机制);SUPPORTS:有事务则加入,没有则以非事务执行;NOT_SUPPORTED:以非事务执行,挂起现有事务;NEVER:以非事务执行,有事务则抛异常;MANDATORY:必须存在事务,否则抛异常。REQUIRES_NEW 常用于日志记录等需要独立提交的场景。
隔离级别(Isolation) 控制并发事务的可见性。READ_UNCOMMITTED(读未提交,最低级别,可能脏读)、READ_COMMITTED(读已提交,大多数数据库默认,防止脏读但可能不可重复读)、REPEATABLE_READ(可重复读,MySQL 默认,防止不可重复读但可能幻读)、SERIALIZABLE(串行化,最高级别,完全隔离但性能最差)、DEFAULT(使用数据库默认)。实际开发中通常使用数据库默认级别,配合乐观锁(@Version)处理并发更新冲突。
@Transactional(
propagation = Propagation.REQUIRES_NEW,
isolation = Isolation.READ_COMMITTED,
rollbackFor = Exception.class,
timeout = 30,
readOnly = false
)
public void processPayment(PaymentRequest request) {
// 独立事务,不受外层事务影响
}
事务失效场景:方法非 public、同类内部调用、异常被 try-catch 吞掉、数据库引擎不支持事务(如 MyISAM)。排查事务问题时,可开启 Spring 事务日志(logging.level.org.springframework.transaction=DEBUG)观察事务的开启、提交、回滚过程。
三、Python Web 开发
3.1 FastAPI 框架
FastAPI 是 Python 生态中增长最快的现代 Web 框架,基于 Starlette(ASGI)和 Pydantic 构建,以高性能和自动文档生成著称。
路由与请求处理通过装饰器定义,支持所有 HTTP 方法。路径参数通过花括号声明,查询参数通过函数参数自动推断。FastAPI 利用 Python 类型注解实现自动参数解析和校验,无需额外的验证库。async def 定义异步端点,适合 I/O 密集型操作;普通 def 在线程池中执行,适合 CPU 密集型或阻塞操作。
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel, EmailStr, Field
app = FastAPI(title="用户管理 API", version="1.0.0")
class UserCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: EmailStr
age: int = Field(..., ge=18, le=120)
class UserResponse(BaseModel):
id: int
name: str
email: str
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
# 创建用户逻辑
return UserResponse(id=1, name=user.name, email=user.email)
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
return UserResponse(id=user_id, name="张三", email="zhangsan@example.com")
@app.get("/search")
async def search_users(
keyword: str = Query(..., min_length=1),
page: int = Query(1, ge=1),
size: int = Query(20, ge=1, le=100)
):
return {"keyword": keyword, "page": page, "size": size}
Pydantic 模型是 FastAPI 的数据验证核心。继承 BaseModel 定义数据结构,字段类型注解自动触发校验。Field() 提供额外约束(范围、长度、正则表达式)。嵌套模型、泛型模型、模型继承均被支持。response_model 参数控制响应输出,自动过滤未声明的字段(如密码等敏感信息),并执行数据序列化。
依赖注入通过 Depends 实现,是 FastAPI 最强大的特性之一。依赖可以是函数或类,支持嵌套依赖和子依赖。常见用途包括:数据库会话管理、用户认证、权限校验、分页参数提取。依赖的返回值注入到端点参数中,生命周期通过 yield 控制(yield 前为准备阶段,yield 后为清理阶段)。
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
# 数据库会话依赖
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
# 认证依赖
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db)
) -> User:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
user = await db.get(User, payload["sub"])
if not user:
raise HTTPException(status_code=401, detail="无效的用户")
return user
# 端点中使用
@app.get("/users/me", response_model=UserResponse)
async def get_me(current_user: User = Depends(get_current_user)):
return current_user
异步支持是 FastAPI 的核心优势。基于 ASGI 协议和 asyncio,FastAPI 可原生处理并发连接。async def 端点中应使用异步库(如 httpx、motor、databases),避免阻塞事件循环。对于同步阻塞操作(如传统 ORM),FastAPI 自动在线程池中执行,但会损失部分并发性能。SQLAlchemy 2.0+ 提供了完整的异步支持(AsyncSession),推荐与 FastAPI 配合使用。
自动文档是 FastAPI 的标志性功能。启动后自动在 /docs 提供 Swagger UI,在 /redoc 提供 ReDoc 界面。文档基于 OpenAPI 3.0 规范,包含所有端点、参数、请求体、响应模型的完整描述。可通过 openapi_url、docs_url、redoc_url 参数自定义路径或禁用。文档可直接用于 API 测试,极大提升了前后端协作效率。
3.2 SQLAlchemy ORM
SQLAlchemy 是 Python 生态最成熟的 ORM 框架,2.0 版本引入了统一的异步 API 和更严格的类型支持。
模型定义通过声明式基类实现。SQLAlchemy 2.0 推荐使用 Mapped 类型注解和 mapped_column,替代传统的 Column 声明方式。模型类继承 DeclarativeBase,属性通过类型注解映射到数据库列。关系通过 relationship() 定义,支持懒加载、级联删除、反向引用等配置。
from sqlalchemy import String, Integer, ForeignKey, DateTime
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from datetime import datetime
Base = DeclarativeBase()
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(50), nullable=False)
email: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
orders: Mapped[list["Order"]] = relationship(back_populates="user")
class Order(Base):
__tablename__ = "orders"
id: Mapped[int] = mapped_column(primary_key=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
amount: Mapped[float] = mapped_column(nullable=False)
user: Mapped["User"] = relationship(back_populates="orders")
会话管理通过 Session(同步)或 AsyncSession(异步)实现。会话是 ORM 操作的工作单元,跟踪所有对象的状态变化。session.add() 添加新对象,session.commit() 提交事务,session.rollback() 回滚。异步会话在 FastAPI 中通过依赖注入管理生命周期,确保每个请求使用独立会话并在请求结束时关闭。
# 异步查询示例
async def get_user_orders(session: AsyncSession, user_id: int):
result = await session.execute(
select(Order)
.where(Order.user_id == user_id)
.order_by(Order.created_at.desc())
.limit(20)
)
return result.scalars().all()
# 关联查询
async def get_user_with_orders(session: AsyncSession, user_id: int):
result = await session.execute(
select(User)
.options(selectinload(User.orders))
.where(User.id == user_id)
)
return result.scalars().first()
查询构建使用 SQLAlchemy 2.0 的 select() 风格,替代旧的 session.query() 风格。select() 构建查询对象,session.execute() 执行。where() 过滤条件,order_by() 排序,limit()/offset() 分页,join() 关联查询。selectinload() 和 joinedload() 控制关联加载策略,前者通过额外 SELECT 加载关联数据(适合一对多),后者通过 JOIN 加载(适合多对一)。
from sqlalchemy import select, func
# 分页查询
async def search_users(
session: AsyncSession,
keyword: str,
page: int = 1,
size: int = 20
):
offset = (page - 1) * size
query = (
select(User)
.where(User.name.contains(keyword) | User.email.contains(keyword))
.order_by(User.created_at.desc())
.offset(offset)
.limit(size)
)
result = await session.execute(query)
return result.scalars().all()
# 聚合查询
async def get_order_stats(session: AsyncSession, user_id: int):
result = await session.execute(
select(
func.count(Order.id).label("total"),
func.sum(Order.amount).label("total_amount"),
func.avg(Order.amount).label("avg_amount")
).where(Order.user_id == user_id)
)
return result.one()
Alembic 迁移是 SQLAlchemy 的数据库迁移工具。alembic init 初始化迁移环境,alembic revision --autogenerate -m "描述" 根据模型变更自动生成迁移脚本,alembic upgrade head 应用迁移。迁移文件包含 upgrade() 和 downgrade() 函数,支持正向和回滚操作。
3.3 部署方案
Python Web 应用的部署涉及 ASGI 服务器、进程管理和反向代理三个层次。
Uvicorn 是基于 uvloop 和 httptools 的高性能 ASGI 服务器,是 FastAPI 的推荐运行环境。uvloop 是 asyncio 的高性能事件循环实现,基于 libuv(Node.js 同款)。Uvicorn 支持 HTTP/1.1、HTTP/2、WebSocket,单进程可处理数千并发连接。开发环境直接运行 uvicorn main:app --reload,生产环境需配合进程管理器。
# 开发环境
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# 生产环境(多进程)
gunicorn main:app \
-w 4 \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--access-logfile - \
--error-logfile -
Gunicorn 是 Python 生态最成熟的 WSGI/ASGI 进程管理器。通过 -w 参数指定工作进程数(推荐 2 * CPU核心数 + 1),-k 指定 worker 类型。运行 FastAPI 时使用 uvicorn.workers.UvicornWorker,将每个进程变为异步 ASGI worker。Gunicorn 负责进程管理、优雅重启、日志轮转等运维任务。
Nginx 反向代理 是生产部署的标准配置。Nginx 作为前端代理,负责 SSL 终止、静态文件服务、请求限流、负载均衡。Gunicorn 运行在后端端口,不直接暴露给外部网络。Nginx 配置中设置 proxy_pass 指向 Gunicorn,配置 proxy_set_header 传递真实客户端 IP 和协议信息。
server {
listen 80;
server_name api.example.com;
# 静态文件
location /static/ {
alias /app/static/;
expires 30d;
}
# 反向代理
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
# 限流
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://127.0.0.1:8000;
}
}
Docker 容器化是现代部署的标准方式。多阶段构建减小镜像体积,非 root 用户运行提升安全性,健康检查确保容器可用性。Docker Compose 编排应用、数据库、缓存等服务。Kubernetes 进一步提供自动扩缩容、服务发现、配置管理等能力。
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1
CMD ["gunicorn", "main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]
四、跨框架对比
| 概念 | ASP.NET Core | Spring Boot | FastAPI |
|---|---|---|---|
| 依赖注入 | 内置 DI 容器(Transient/Scoped/Singleton) | Spring IoC(singleton/prototype/request/session) | Depends(函数/类依赖) |
| ORM | EF Core(LINQ、迁移) | JPA/MyBatis(Repository/XML) | SQLAlchemy(声明式、Alembic) |
| 中间件 | IMiddleware 管道 | Filter/Interceptor/HandlerInterceptor | Starlette Middleware |
| 配置系统 | IConfiguration + IOptions | @ConfigurationProperties + @Value | Pydantic Settings / env vars |
| 验证 | Data Annotations / FluentValidation | JSR-303 / Hibernate Validator | Pydantic 类型注解 |
| 异步支持 | async/await(原生) | 虚拟线程(Java 21+)/ CompletableFuture | async/await(原生 ASGI) |
| 文档生成 | Swagger/Swashbuckle | SpringDoc OpenAPI | 自动生成(OpenAPI 3.0) |
| 事务管理 | DbContext 事务 / TransactionScope | @Transactional(AOP 代理) | 手动 / 依赖注入管理 |
| 安全认证 | ASP.NET Core Identity / JWT | Spring Security(认证链) | OAuth2 / JWT 手动集成 |
| 部署 | Kestrel + Nginx / IIS / Docker | Tomcat/Jetty(内嵌) + Nginx | Uvicorn + Gunicorn + Nginx |
| 性能 | 高(基准测试领先) | 中(JVM 启动慢,运行时稳定) | 高(ASGI + uvloop) |
| 学习曲线 | 中等 | 陡峭(概念多) | 平缓(Pythonic) |
选型建议
- 企业级复杂系统:Spring Boot 生态最完善,适合大型团队、复杂业务逻辑、已有 Java 技术栈的场景。
- 高性能 API 服务:ASP.NET Core 在基准测试中表现优异,适合对吞吐量有极致要求的场景。
- 快速原型 / 数据科学后端:FastAPI 开发效率最高,与 Python 数据科学生态无缝集成,适合 ML 模型服务、快速迭代项目。
- 跨平台需求:ASP.NET Core 和 FastAPI 均支持 Linux/macOS/Windows,Spring Boot 依赖 JVM 但 JVM 本身跨平台。
五、学习资源推荐
.NET / ASP.NET Core
- 官方文档:https://docs.microsoft.com/aspnet/core — 微软官方文档,质量极高,包含教程、参考、最佳实践
- ASP.NET Core in Action(Andrew Lock) — 深入讲解中间件、依赖注入、配置等核心机制
- Pro ASP.NET Core(Adam Freeman) — 全面覆盖 MVC、Web API、Blazor 等
- YouTube: Nick Chapsas — 高质量的 .NET 性能优化和最佳实践视频
Java / Spring Boot
- 官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/ — Spring Boot 参考文档
- Spring Boot 编程思想(小马哥) — 中文视角深入解读 Spring Boot 自动配置原理
- Spring in Action(Craig Walls) — 经典入门,覆盖 Spring 核心、Boot、Cloud
- Spring 实战(汪云飞) — 中文书籍,适合有一定 Java 基础的开发者
- Baeldung:https://www.baeldung.com/ — Spring 生态最全的技术博客,覆盖几乎所有主题
Python / FastAPI
- 官方文档:https://fastapi.tiangolo.com/ — 文档质量极高,包含教程和 API 参考
- TestDriven.io:https://testdriven.io/ — FastAPI + TDD 实战教程
- Full Stack FastAPI Template — 官方全栈模板,包含前端、后端、数据库、认证的完整项目
- Talk Python To Me 播客 — Python 生态最新动态和技术访谈
通用后端知识
- Designing Data-Intensive Applications(Martin Kleppmann) — 数据存储、分布式系统经典
- RESTful Web APIs(Leonard Richardson) — REST 设计原则和实践
- High Performance Browser Networking — 理解 HTTP/2、HTTP/3、WebSocket 等网络协议
- System Design Primer:https://github.com/donnemartin/system-design-primer — 系统设计面试准备