当前位置: 首页 > article >正文

【学习总结|DAY025】JAVA-WEB基础

在 Web 开发领域,SpringBoot 已成为重要的技术框架,其简化配置和快速开发的特性深受开发者喜爱。本文将详细介绍 SpringBoot Web 开发的基础知识,涵盖从入门程序搭建到 HTTP 协议解析,再到分层解耦实践等内容,助力读者快速上手。

一、SpringBoot Web 入门

(一)Spring 生态与 SpringBoot 优势

Spring 发展出庞大生态,提供众多子项目,各有特定功能。SpringBoot 尤为突出,它极大简化配置过程,让开发者能迅速构建应用程序,提高开发效率,在企业开发中应用广泛,成为主流选择。

(二)入门程序实践

  1. 创建工程与依赖配置:首先访问 start.spring.io 创建 SpringBoot 工程,需勾选 web 开发依赖,此依赖集包含如 spring-boot-starter-web 等关键模块,为后续开发提供基础支持。例如,若开发一个简单的 Web 应用展示用户信息,这些依赖可确保应用能正常处理 HTTP 请求与响应。
  2. 定义请求处理类与方法:创建 HelloController 类,添加 hello 方法,并使用 @RestController 和 @RequestMapping("/hello") 注解。如下所示:
@RestController
@RequestMapping("/hello")
public class HelloController {
    public String hello(String name) {
        System.out.println("HelloController... hello : " + name);
        return "Hello " + name + " ~ ";
    }
}

在浏览器访问 http://localhost:8080/hello?name=Heima,即可触发该方法,返回 “Hello Heima ~”。

(三)入门程序剖析

  1. 起步依赖解析spring-boot-starter-web 是核心依赖,其中嵌套了如 spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcat 等依赖,还引入了 Jakarta EE 相关的 jakarta.annotation-api 以及 Apache Tomcat 相关的 org.apache.tomcat.embed 系列依赖,同时涵盖 spring-web 和 spring-webmvc 等,这些依赖协同工作,支撑起 Web 应用的运行环境。
  2. 启动流程详解:在 main 方法启动应用后,会进行一系列初始化操作。如 Tomcat 会在 o.s.b.w.embedded.tomcat.TomcatwebServer 类中被初始化并监听 8080 端口,随后启动 Servlet 引擎,初始化 Spring 嵌入式 WebApplicationContext,完成这些步骤后,Tomcat 正式启动,整个应用便可接收并处理请求。

二、HTTP 协议解析

(一)协议概述

HTTP 协议(Hyper Text Transfer Protocol)是浏览器和服务器之间数据传输的规则制定者。它基于 TCP 协议,采用请求 - 响应模型,每次请求对应一次响应,但自身无状态,这意味着不同请求间无法直接共享数据,不过也正因如此,其数据传输速度较快。

(二)请求数据格式与获取

  1. 请求数据结构:请求数据分为请求行、请求头和请求体。请求行包含请求方式、资源路径和协议版本;请求头从第二行开始,格式为 key:value,如 Host 表示请求的主机名,User-Agent 标识浏览器版本等;请求体在 POST 请求中用于存放请求参数,GET 请求参数则在请求行中,且 GET 请求大小在浏览器中有一定限制。例如:
GET /brand/findAll?name=OPPO&status=1 HTTP/1.1
Accept: text/html, application/xhtml+xml, application/xml; q=0.9, image/avif, image/webp, image/apng, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN, zh;q=0.9
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/...
  1. 数据获取方式:Web 服务器(如 Tomcat)会解析请求数据并封装为 HttpServletRequest 对象,开发者无需直接操作协议。在 Controller 方法中,可通过该对象获取各种请求信息,如:
@RequestMapping("/request")
public String request(HttpServletRequest request) {
    String name = request.getParameter("name"); 
    String uri = request.getRequestURI(); 
    String url = request.getRequestURL().toString(); 
    String userAgent = request.getHeader("User-Agent"); 
    String method = request.getMethod(); 
    String queryString = request.getQueryString(); 
    return "request success";
}

(三)响应数据格式与设置

  1. 响应数据构成:响应数据由响应行、响应头和响应体组成。响应行包含协议、状态码和描述,如 200 OK 表示客户端请求成功;响应头从第二行开始,格式为 key:value,如 Content-Type 指示响应内容类型;响应体存放实际响应数据。例如:
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 10 May 2022 07:51:07 GMT
Keep-Alive: timeout=60
Connection: keep-alive
[{id: 1, brandName:"阿里巴巴", companyName:"腾讯计算机系统有限公司",description:"玩玩玩"}]
  1. 数据设置方法:服务器同样封装了响应数据为 HttpServletResponse 对象。开发者可在 Controller 方法中进行设置,如:
@RequestMapping("/response")
public void response(HttpServletResponse response) throws IOException {
    response.setStatus(401);
    response.setHeader("itheima","itheima");
    response.getWriter().write("<h1>Hello Response</h1>");
}

也可使用 ResponseEntity 进行更灵活的设置:

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

通常情况下,服务器会根据请求处理逻辑自动设置响应状态码和响应头,开发者无需手动指定。

三、SpringBoot Web 案例:用户列表渲染展示

(一)准备工作

  1. 创建 SpringBoot 工程,勾选 web 依赖和 lombok(用于简化 Java 代码编写)。
  2. 引入用户数据文件(user.txt)和前端静态页面,将静态资源文件存放在 resources/staticresources/resources 或 resources/public 目录下。
  3. 定义实体类 User 封装用户信息,例如:
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private LocalDateTime updateTime;

    public User(Integer id, String username, String password, String name, Integer age, LocalDateTime updateTime) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.name = name;
        this.age = age;
        this.updateTime = updateTime;
    }
}

(二)服务端程序开发

@RestController
@RequestMapping("/list")
public class UserController {
    // 原始实现方式,复用性差
    public List<User> list() {
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
        ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

        return 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 uTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            return new User(id, username, password, name, age, uTime);
        }).collect(Collectors.toList());
    }
}

这种实现方式将数据读取、解析和响应逻辑都写在 Controller 中,复用性差且难以维护。

四、分层解耦优化

(一)三层架构介绍

遵循单一职责原则,将项目分为三层:

  1. Controller 层:负责接收前端请求,处理后响应数据,如上述 UserController 中的 list 方法,接收请求并调用 Service 层获取数据后返回给前端。
  2. Service 层:处理具体业务逻辑,如对用户数据进行业务相关的处理、验证等操作。在用户列表案例中,UserServiceImpl 实现类会调用 Dao 层获取数据并进行解析封装成 User 对象集合。
  3. Dao 层(Data Access Object):即持久层,负责数据访问操作,如从文件、数据库等数据源读取或写入数据。UserDaoImpl 实现类实现了从 user.txt 文件读取数据的功能。

(二)分层解耦实现

  1. IOC(控制反转)与 DI(依赖注入)应用
    • 将 Dao 及 Service 层的实现类交给 IOC 容器管理,通过在类上添加 @Component@Controller@Service@Repository 等注解实现。例如:
@Component
public class UserDaoImpl implements UserDao {
    //...
}

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    //...
}

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    //...
}
  • 为 Controller 及 Service 注入运行时所依赖的对象,使用 @Autowired 注解(若存在多个同类型 bean,可结合 @Primary@Qualifier 或使用 @Resource 注解解决)。
  1. 优化后代码示例
@RestController
@RequestMapping("/list")
public class UserController {
    @Autowired
    private UserService userService;

    public List<User> list() {
        return userService.list();
    }
}

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public List<User> list() {
        List<String> lines = userDao.list();
        return 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 uTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            return new User(id, username, password, name, age, uTime);
        }).collect(Collectors.toList());
    }
}

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

通过分层解耦和 IOC/DI 机制,代码结构更清晰,各层职责明确,提高了复用性和可维护性。

在 SpringBoot Web 开发中,理解并掌握这些基础知识是构建高效、可维护应用的关键。从入门程序搭建到深入理解 HTTP 协议,再到运用分层解耦优化项目结构,每一步都为开发者在 Web 开发领域的进阶奠定坚实基础。希望本文能帮助读者更好地理解和应用 SpringBoot Web 开发技术,在实际项目中发挥作用。


http://www.kler.cn/a/456954.html

相关文章:

  • 记录第一次跑YOLOV8做目标检测
  • tar.gz压缩文件在linux上解压异常问题:gzip:stdin:invalid compressed data
  • Object.defineProperty() 完整指南
  • java里classpath都包含哪些范围?
  • WEB服务器的部署和优化
  • 【JAVA】Java常用注解汇总
  • 代码随想录算法训练营第十六天-二叉树-513.找树左下角的值
  • python常用内建模块:struct
  • React(一)—— router/useRef/useState
  • 地理数据库Telepg面试内容整理-如何解决大规模地理数据导入时出现的性能瓶颈
  • 灾备方案和架构类型、跨区域
  • hive中的四种排序类型
  • SVN和Git
  • Day1 微服务 单体架构、微服务架构、微服务拆分、服务远程调用、服务注册和发现Nacos、OpenFeign
  • 代码解析:安卓VHAL的AIDL参考实现
  • Android 自定义shell命令
  • 4.银河麒麟V10(ARM) 离线安装 MySQL
  • 在线学习平台-项目技术点-前台
  • Mono里运行C#脚本6—mono加载EXE文件和DLL文件保存的HASH表
  • PPO(近端策略优化)算法基本原理
  • 跨境办公的网络如何选择?
  • [Rust开发]actix_webmiddleware 中间件
  • CSS系列(42)-- Backdrop Filter详解
  • 基于深度学习的图像超分辨率重建
  • LeetCode 349. 两个数组的交集 (C++实现)
  • nginx反向代理单台 Web 服务器实验