Web后端开发

Web后端开发

Web基础知识

  • 静态资源:服务器上存储的不会改变的数据,通常不会根据用户的请求而变化。比如:HTML、CSS、JS、图片、视频等(负责页面展示)
  • 动态资源:服务器端根据用户请求和其他数据动态生成的,内容可能会在每次请求时都发生变化。比如:Servlet、JSPSpring框架)等(负责逻辑处理)
  • B/S架构:Browser/Server,浏览器/服务器架构模式。客户只需浏览器,应用程序的逻辑和数据都存在服务器端。(维护方便 体验一般)
  • C/S架构:Client/Server,客户端/服务器架构模式。需要单独开发维护客户端。(体验不错 开发维护麻烦)

Spring

  • 官网:https://spring.io
  • Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能。

Spring Boot【官方推荐、企业主流】可以帮助我们非常快速的构架应用程序、简化开发、提高效率

入门程序

  • 需求:基于SpringBoot开发一个Web应用,浏览器发起请求/hello之后,给浏览器返回一个字符串“Hello Xxx”

步骤

①创建springboot工程,并勾选web开发相关依赖

②定义HelloController类,添加方法hello,并添加注解(定义请求处理方法)

③运行启动类,测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@RestController //表示当前类是一个请求处理类
public class HelloController {

    @RequestMapping("/hello")//标识请求路径
    public String hello(String name){
        System.out.println("name" + name);
        //给前端响应数据
        return "Hello" + name + "~";
    }
    

然后到Springboot启动类中运行debug:若出现以下界面则表示运行成功了

然后在浏览器输入localhost:8080/hello?name=itheima

出现以上界面则说明成功完成了

Spring官方脚手架连接不上解决方案

如果出现上面情况,可以将URL换成阿里云的

后面的和上面的入门程序的步骤一样

入门程序剖析

  • 为什么一个main方法就将web应用启动类了?

起步依赖:

  • spring-boot-starter-web:包含了web应用开发所需要的常见依赖
  • spring-boot-starter-test:包含了单元测试所需要的常见依赖
  • 官方提供的starter:

https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/#using.build-systems.starters

其中的tomcat服务器是内嵌的,一个main方法就可以将tomcat服务器启动起来

HTTP协议

请求协议

请求数据格式

概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。

超文本:可以互相链接、跳转的文本,也就是包含超链接的文本。

  • 普通文本:只能从头到尾读,不能跳转。
  • 超文本:里面有链接,点一下就能跳到另一篇文档、图片、网页。
  • HTTP 就是专门用来在网络上传输这种带链接的超文本内容的协议,所以叫 “超文本传输协议”。
  • 特点:

    1.基于TCP协议的:面向连接,安全

    2.基于请求-响应模型的:一次请求对应一次响应

    3.HTTP协议是无状态的协议:对于事物处理没有记忆能力。每次请求-响应都是独立的

    • 缺点:多次请求间不能共享数据
    • 优点:速度快

常见的请求头:

请求数据获取
  • Web服务器(Tomcat)对HTTP协议的请求数据进行解析,并进行了封装(HttpServletRequest),在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷
  • 通过HttpServerletRequest对象获取请求数据,里面封装了所有的请求信息

@RestController //表示当前类是一个请求处理类

@RequestMapping("/hello") //标识请求路径

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

@RestController
public class RequestController {
    @RequestMapping("/request")
    public String request(HttpServletRequest request){
        //1.获取请求方式
        String method = request.getMethod();
        System.out.println("请求方式" + method);

        //2.获取请求url地址
        String url = request.getRequestURL().toString();  //http://localhost:8080/request
        System.out.println("请求地址" + url);

        String uri = request.getRequestURI();
        System.out.println("请求URI" + uri);

        //3.获取请求协议
        String protocol = request.getProtocol();
        System.out.println("请求协议" + protocol);

        //4.获取请求参数 - name
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        System.out.println("请求参数 - name" + name + " age" + age);

        //5.获取请求头 - Accept(如果要获取其他请求头,将Accept替换即可)
        String accept = request.getHeader("Accept");
        System.out.println("请求头 - Accept" + accept);

        return "OK";
    }
}

在浏览器输入:localhost:8080/request?name=itheima&age=18即可得到下方结果

响应协议

响应数据格式

常见的响应状态码:

重定向(3xx):底层会获取到多次请求

例如:在网页输入http://www.baidu.com/

经过重定向再次请求:https://www.baidu.com/

常见状态码:

响应数据设置
  • Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

封装方式一:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@RestController
public class ResponseController {
    /*
    * 方式一:使用HttpServletResponse对象
    * */
    @RequestMapping("/response")
    public void response(HttpServletResponse response) throws IOException {
        //1.设置响应状态码
        response.setStatus(401);
        //2.设置响应头
        response.setHeader("name", "itheima");
        //3.设置响应体(数据)
        response.getWriter().write("<h1>hello response</h1>");
    }
}

封装方式二:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@RestController
public class ResponseController {
    /*
    方式二:使用ResponseEntity对象
    */

    @RequestMapping("/response2")
    public ResponseEntity<String> response2() {
        return ResponseEntity.status(401)//响应状态码
                .header("name", "javaweb-ai")//响应头
                .body("<h1>hello response</h1>");//响应体
    }
}

结果:

注意:响应状态码 和 响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头。

SpringBootWeb案例

需求:基于SpringBoot开发web程序,完成用户列表的渲染展示

当在浏览器地址栏,访问前端静态页面(http://localhost:8080/usre.html)后,在前端页面上,会发送ajax请求,请求服务端(http://localhost:8080/list),服务端程序加载 user.txt 文件中的数据,读取出来后最终给前端页面响应json格式的数据,前端页面再将数据渲染展示在表格中。

1.准备工作:

  • 创建一个SpringBoot工程,并勾选web依赖、lombok
  • 引入资料中准备好的用户数据文件(user.txt),及前端静态页面

  • 定义一个实体类,用来封装用户信息

com.itheima 下再定义一个包 pojo,专门用来存放实体类。 在该包下定义一个实体类User:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


import java.time.LocalDateTime;

/*
* 用户信息
* */
@Data   //目的:自动生成getter和setter方法
@NoArgsConstructor  //无参构造
@AllArgsConstructor //全参构造
public class User {
    private Integer id; //在项目中,建议使用包装类(目的:不要默认值)
    private String username;
    private String password;
    private String name;
    private Integer age;
    private LocalDateTime updateTime;
}

2.开发服务端程序,接收请求,读取文本数据并响应

由于在案例中,需要读取文本中的数据,并且还需要将对象转为json格式,所以这里呢,我们在项目中再引入一个非常常用的工具包hutool。 然后调用里面的工具类,就可以非常方便快捷的完成业务操作。

  • pom.xml中引入依赖
1
2
3
4
5
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.27</version>
</dependency>
  • com.itheima包下新建一个子包controller,在其中创建一个UserController
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.itheima.controller;

import cn.hutool.core.io.IoUtil;
import com.itheima.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/*
 * 用户信息controller
 * */
@RestController  //封装了@ResponseBody -> 作用:将controller返回值直接作为响应体的数据直接响应;返回值是对象/集合->json-> 响应
public class UserController {
    @RequestMapping("/list")
    public List<User> list() throws Exception {
        //1.加载并读取user.txt文件,获取用户数据
        //通过字节码对象来获取到类加载器
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
        List<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

        //2.解析用户信息,封装为User对象 -> list集合
        //遍历集合
        List<User> userList = lines.stream().map(line -> {
            // 根据“,”进行截取
            String[] parts = line.split(",");
            //获取信息
            //5,zhaoyun,1234567890,赵云,27,2024-07-16 11:03:28
            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"));//注意:parts[5]DTF是写在一个一个()里的,如果没有写在一个括号里,虽然不会报红,但是运行时会报错

            return new User(id, username, password, name, age, updateTime);
        }).collect(Collectors.toList());//封装到集合当中


        //3.返回数据(json)
        return userList;

    }
}

3.启动服务测试,访问:http://localhost:8080/user.html

@ResponseBody注解的作用

  • 将controller方法的返回值直接写入HTTP响应体
  • 如果是对象或集合,会先转为json,再响应
  • @RestController = @Controller + @ResponseBody

分层解耦

由于上一个项目的代码有着复用性差、难以维护的缺点,所以引入了该小节的内容

三层架构

为什么要进行拆分:遵循单一职责原则,便于复用、后期维护

  • controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据
  • service:业务逻辑层,处理具体的业务逻辑
  • dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查

流程:

对比:

分层解耦

  • 耦合:衡量软件中各个层/各个模块的依赖关联程度
  • 内聚:软件中各个功能模块内部的功能联系
  • 软件设计原则:高内聚低耦合

  • 控制反转Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想成为控制反转
  • 依赖注入Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
  • Bean对象:IOC容器中创建、管理的对象,称之为Bean

IOC & DI入门

1.将Dao及Service层的实现类,交给IOC容器管理

(@Component:将当前类交给IOC容器管理)

注意:是加在实现类上,而非接口上

2.为Controller及Service注入运行时所依赖的对象

(@Autowired:应用程序运行时,会自动的查询该类型的Bean对象,并赋值给改成员变量)

①修改rController层:

②分别修改Dao层和Service层:

③Controller层和Server层注入对象:

IOC详解

  • 要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一:

注意:声明bean的时候,可以通过注解的value属性指定bean的名字,如果没有指定,默认为类名首字母小写

  • 前面声明的bean的四大注解,想要生效,还需要被组件扫描注解**@ComponentScan**扫描
  • 该注解虽然没有显示配置,但是实际上已经包含在了启动类声明注解**@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包**

按住ctrl键点击@SpringBootApplication即可看到@ComponentScan

DI详解

实际开发中,前两种使用较多

  • Autowired注解,默认是按照类型进行注入的

  • 如果存在多个相同类型的bean,将会报出如下错误:

解决方案:

注意:方案二中的@Qualifier中要写这个类的名字(默认是首字母小写,其他不变)

@Aurowired是Spring框架提供的注解,而@Resource是JavaEE规范提供的

@Aurowired默认是按照类型注入的,而@Resource默认是按照名称注入的

本站于2026年3月31日建立
使用 Hugo 构建
主题 StackJimmy 设计