后端Web基础

后端Web基础

理论篇

  • 后端资源类型与架构

    • 静态资源:HTML、CSS、JS、图片、音频、视频等,存储于服务器,不随请求变化。
    • 动态资源:根据请求动态生成(如早期 Servlet/JSP;企业主流采用 Spring 体系)。
    • 部署与通信:动态资源通常运行在 Web 服务器(Tomcat)中,浏览器与服务器基于 HTTP 协议通信。
    • 架构模式:
      • BS(Browser/Server):客户端仅需浏览器,逻辑与数据在服务端(优点:维护方便;缺点:体验一般)。
      • CS(Client/Server):需专门客户端(优点:体验好;缺点:开发维护麻烦)。
  • Spring 与 SpringBoot

    • Spring 家族:以 Spring Framework 为核心,生态丰富(依赖注入、事务、Web、数据访问等)。
    • 问题:直接使用 Spring Framework 配置繁琐、入门难度大。
    • SpringBoot 特点:简化配置、快速开发;内置起步依赖(starter),可内嵌 Tomcat 启动 Web 应用。
  • HTTP 协议概述与特点

    • 定义:超文本传输协议,规定浏览器与服务器之间的数据传输规则。
    • 特点:
      • 基于 TCP:面向连接、可靠。
      • 请求-响应模型:一次请求对应一次响应。
      • 无状态:不记录会话状态(共享数据需会话技术 Cookie/Session)。
    • 学习重点:请求协议(请求行/请求头/请求体)、响应协议(响应行/响应头/响应体)。
  • HTTP 请求协议

    • GET:
      • 请求行:方法 GET、资源路径(含参数)、协议/版本。
      • 请求头:key: value。
      • 请求体:无(参数在请求行)。
    • POST:
      • 请求行:方法 POST、资源路径、协议/版本。
      • 请求头:key: value。
      • 请求体:有(参数在请求体,头部与体之间有空行)。
    • GET 与 POST 区别(本节结论):
      • GET 参数在请求行,长度有限制,安全性低(地址栏可见)。
      • POST 参数在请求体,长度无限制,安全性相对高。
  • HTTP 响应协议

    • 响应行:协议/版本、状态码、状态描述(如 HTTP/1.1 200 OK)。
    • 响应头:key: value(Content-Type、Content-Length、Content-Encoding、Cache-Control、Set-Cookie 等)。
    • 响应体:数据内容(与响应头之间有空行)。
    • 重点状态码:200(OK)、404(Not Found)、500(Internal Server Error)。
  • SpringBoot Web 案例流程

    • 访问静态页面 → 页面 Ajax 请求后端接口 → 服务端读取 user.txt 数据,返回 JSON → 前端渲染表格。
  • 分层解耦与三层架构

    • 原则:单一职责;高内聚、低耦合。
    • 三层:
      • Controller:接收请求、响应数据。
      • Service:业务逻辑处理。
      • Dao:数据访问(增删改查)。
    • 好处:复用强、便于维护与扩展;层与层相互解耦。
  • IOC 与 DI

    • IOC(控制反转):对象创建交由容器管理(IOC 容器 / Spring 容器),容器中对象称为 bean。
    • DI(依赖注入):容器为程序运行时提供所需对象(如为 Controller 注入 Service)。
    • Bean 声明注解:
      • @Component:通用 Bean。
      • @Controller:控制层。
      • @Service:业务层。
      • @Repository:数据访问层。
    • 组件扫描:由 @SpringBootApplication(内含 @ComponentScan)开启,默认扫描启动类所在包及子包。
    • 注入方式:@Autowired 支持属性注入、构造器注入、setter 注入;多实现冲突通过 @Primary、@Qualifier、@Resource 解决。

代码篇


SpringBoot Web 入门与内嵌 Tomcat

作用/概念简述

  • 创建 SpringBoot Web 工程,运行引导类 main 方法,内嵌 Tomcat 启动 Web 应用;Controller 暴露 /hello 接口。

通用模版

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

// 控制器
@RestController
public class HelloController {
  @RequestMapping("/hello")
  public String hello(String name){
    return "Hello " + name;
  }
}

属性/知识点表格

说明
spring-boot-starter-web启动器,内含 Web 所需依赖,并通过依赖传递带入内嵌 Tomcat
main 方法启动内嵌 Tomcat,默认 8080 端口
@RestController等价 @Controller + @ResponseBody(返回值直接写入响应体)
@RequestMapping映射请求路径

片段代码案例

@RestController // 标识请求处理类
public class HelloController {
  @RequestMapping("/hello")
  public String hello(String name){
    System.out.println("HelloController ... hello: " + name);
    return "Hello " + name;
  }
}

获取请求数据(HttpServletRequest)

作用/概念简述

  • Web 服务器解析 HTTP 请求并封装为 HttpServletRequest,方法入参直接接收,用于获取参数、路径、方法、请求头。

通用模版

@RequestMapping("/request")
public String request(HttpServletRequest request){
  String p = request.getParameter("key");
  String uri = request.getRequestURI();
  String url = request.getRequestURL().toString();
  String method = request.getMethod();
  String header = request.getHeader("User-Agent");
  return "ok";
}

属性/知识点表格

API说明
getParameter(name)获取请求参数
getRequestURI()获取请求路径(不含协议主机端口)
getRequestURL()获取完整 URL 字符串
getMethod()获取请求方法(GET/POST)
getHeader(name)获取请求头

片段代码案例

@RestController
public class RequestController {
  @RequestMapping("/request")
  public String request(HttpServletRequest request){
    String name = request.getParameter("name");
    String age = request.getParameter("age");
    System.out.println("name = " + name + ", age = " + age);

    String uri = request.getRequestURI();
    String url = request.getRequestURL().toString();
    System.out.println("uri = " + uri);
    System.out.println("url = " + url);

    String method = request.getMethod();
    System.out.println("method = " + method);

    String header = request.getHeader("User-Agent");
    System.out.println("header = " + header);
    return "request success";
  }
}

设置响应数据(HttpServletResponse/ResponseEntity)

作用/概念简述

  • 通过 HttpServletResponse/ResponseEntity 设置响应状态码、响应头与响应体。

通用模版

// 方式一:HttpServletResponse
response.setStatus(状态码);
response.setHeader("k","v");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("内容");

// 方式二:ResponseEntity
return ResponseEntity.status(状态码).header("k","v").body("内容");

属性/知识点表格

说明
setStatus设置响应状态码
setHeader设置响应头
setContentType响应体内容类型与编码
ResponseEntity构造响应(状态/头/体)链式写法

片段代码案例

@RestController
public class ResponseController {
  @RequestMapping("/response")
  public void response(HttpServletResponse response) throws IOException {
    response.setStatus(401);
    response.setHeader("name","itcast");
    response.setContentType("text/html;charset=utf-8");
    response.getWriter().write("<h1>hello response</h1>");
  }

  @RequestMapping("/response2")
  public ResponseEntity<String> response2() {
    return ResponseEntity
      .status(401)
      .header("name","itcast")
      .body("<h1>hello response</h1>");
  }
}

@RestController 与 @ResponseBody

作用/概念简述

  • @ResponseBody:将方法返回值直接写入响应体(对象/集合将转为 JSON);
  • @RestController = @Controller + @ResponseBody,标注在类上即为所有方法生效(前后端分离项目常用)。

通用模版

@RestController
public class XController {
  @RequestMapping("/x")
  public Object x(){ return data; }
}

属性/知识点表格

注解说明
@ResponseBody方法或类级别;返回值直接响应
@RestController组合注解:@Controller + @ResponseBody

片段代码案例

@RestController
public class UserController {
  @RequestMapping("/list")
  public List<User> list(){
    // 返回集合会自动转 JSON
    return List.of();
  }
}

Web 案例:读取 user.txt 返回用户列表(含依赖)

作用/概念简述

  • 读取 resource 下 user.txt 文本为 User 集合,返回 JSON;引入 hutool 工具依赖。

通用模版

<!-- pom.xml 引入 hutool -->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.27</version>
</dependency>
@Data @NoArgsConstructor @AllArgsConstructor
public class User {
  private Integer id;
  private String username;
  private String password;
  private String name;
  private Integer age;
  private LocalDateTime updateTime;
}
@RestController
public class UserController {
  @RequestMapping("/list")
  public String list(){
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
    ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
    List<User> userList = lines.stream().map(line -> { /* 解析封装 */ }).collect(Collectors.toList());
    return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));
  }
}

属性/知识点表格

说明
hutool-all工具库(IoUtil、JSONUtil 等)
资源读取ClassLoader.getResourceAsStream("user.txt")
JSON 格式化JSONConfig.setDateFormat

片段代码案例

@RestController
public class UserController {
  @RequestMapping("/list")
  public String list(){
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
    ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

    List<User> userList = lines.stream().map(line -> {
      String[] parts = line.split(",");
      Integer id = Integer.parseInt(parts[0]);
      String username = parts[1];
      String password = parts[2];
      String name = parts[3];
      Integer age = Integer.parseInt(parts[4]);
      LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
      return new User(id, username, password, name, age, updateTime);
    }).collect(Collectors.toList());

    return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));
    // 或直接 return userList;(依赖 @RestController 自动转 JSON)
  }
}

三层架构拆分(Controller / Service / Dao)

作用/概念简述

  • 将控制、业务、数据访问分离,提高复用、维护与扩展性。

通用模版

// Controller
@RestController
public class UserController {
  private UserService userService = new UserServiceImpl();
  @RequestMapping("/list")
  public List<User> list(){
    return userService.findAll();
  }
}

// Service
public interface UserService { List<User> findAll(); }

public class UserServiceImpl implements UserService {
  private UserDao userDao = new UserDaoImpl();
  public List<User> findAll(){ /* 取数+组装 */ }
}

// Dao
public interface UserDao { List<String> findAll(); }

public class UserDaoImpl implements UserDao {
  public List<String> findAll(){ /* 读取 user.txt */ }
}

属性/知识点表格

职责
Controller接收请求、响应数据
Service业务逻辑处理
Dao数据访问(读写文件/数据库等)

片段代码案例

// Controller
@RestController
public class UserController {
  private UserService userService = new UserServiceImpl();
  @RequestMapping("/list")
  public List<User> list(){
    return userService.findAll();
  }
}

// Service
public interface UserService { List<User> findAll(); }

public class UserServiceImpl implements UserService {
  private UserDao userDao = new UserDaoImpl();
  @Override
  public List<User> findAll() {
    List<String> lines = userDao.findAll();
    return lines.stream().map(line -> {
      String[] parts = line.split(",");
      return new User(
        Integer.parseInt(parts[0]), parts[1], parts[2], parts[3],
        Integer.parseInt(parts[4]),
        LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
      );
    }).collect(Collectors.toList());
  }
}

// Dao
public interface UserDao { List<String> findAll(); }

public class UserDaoImpl implements UserDao {
  @Override
  public List<String> findAll() {
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
    return IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
  }
}

IOC:Bean 声明(@Component 及衍生注解)

作用/概念简述

  • 将对象交由 IOC 容器创建与管理;按层语义使用衍生注解声明组件。

通用模版

@Component   // 通用组件
@Controller  // 控制层
@Service     // 业务层
@Repository  // 数据访问层

属性/知识点表格

注解说明
@Component通用 Bean 声明
@Controller控制层 Bean
@Service业务层 Bean
@Repository数据访问层 Bean
bean 名称可通过 value 指定;默认类名首字母小写

片段代码案例

@Service
public class UserServiceImpl implements UserService { /* ... */ }

@Repository
public class UserDaoImpl implements UserDao { /* ... */ }

组件扫描范围(@SpringBootApplication)

作用/概念简述

  • @SpringBootApplication 内含 @ComponentScan,默认扫描启动类所在包及其子包,确保业务类置于该包结构下。

通用模版

@SpringBootApplication
public class Application { /* ... */ }

属性/知识点表格

注解说明
@SpringBootApplication复合注解,默认组件扫描当前包与子包
@ComponentScan若需自定义扫描路径可显式配置(本节未要求)

片段代码案例

@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
// 将 com.itheima.controller/service/dao 均置于启动类包的子包下

DI:依赖注入(@Autowired 三种方式)

作用/概念简述

  • 容器在运行时为组件注入所依赖对象;@Autowired 按类型装配(属性、构造器、setter)。

通用模版

// 1) 属性注入
@Autowired
private UserService userService;

// 2) 构造器注入(推荐)
private final UserService userService;
@Autowired // 仅有一个构造器时可省略
public XController(UserService userService){ this.userService = userService; }

// 3) setter 注入
private UserService userService;
@Autowired
public void setUserService(UserService userService){ this.userService = userService; }

属性/知识点表格

方式优点缺点
属性注入简洁依赖不显式、封装性可能受损
构造器注入依赖清晰、安全性高(推荐)构造参数多时代码臃肿
setter 注入封装性好、依赖清晰需额外 setter

片段代码案例

@RestController
public class UserController {
  // 属性注入
  @Autowired
  private UserService userService;

  @RequestMapping("/list")
  public List<User> list(){ return userService.findAll(); }
}

多实现冲突注入(@Primary / @Qualifier / @Resource)

作用/概念简述

  • 当容器中存在同类型多个 Bean 时,需指定注入哪一个:默认实现(@Primary)、按名称限定(@Qualifier 或 @Resource)。

通用模版

// 方案一:默认实现
@Primary
@Service
public class UserServiceImpl implements UserService { }

// 方案二:@Qualifier 指定注入 Bean 名称(与 @Autowired 配合)
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;

// 方案三:@Resource 按名称注入(JDK 提供)
@Resource(name = "userServiceImpl")
private UserService userService;

属性/知识点表格

注解提供方注入依据说明
@PrimarySpring默认首选多实现时优先选用
@QualifierSpringBean 名称必须与 @Autowired 一起使用
@ResourceJDKBean 名称不依赖 @Autowired

片段代码案例

@Primary
@Service
public class UserServiceImpl implements UserService { }

@Service
public class UserServiceImpl2 implements UserService { }

@RestController
public class UserController {
  @Autowired
  @Qualifier("userServiceImpl")
  private UserService userService;
}

评论