Day04 Web后端基础


图1 BS架构
目录

1. SpringBoot Web入门

Spring

图2 Spring生态
图3 Spring生态
Spring Boot
图4 SpringFramework与SpringBoot
图5 SpringBoot

1.1 入门程序

package cn.zjy;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController //标识当前类是一个请求处理类
public class HelloController {
    @RequestMapping("/hello")
    public String hello(String name){
        System.out.println("HelloController ... hello : " + name + "(张婧怡)");
        return "Hello " + name + " ~(张婧怡) ";
    }
}
图6 创建SpringBoot入门模块
图7 运行SpringBoot入门模块
Spring官方脚手架连接不上解决方案

https://start.aliyun.com

图8 阿里云创建springboot模块
图8 Maven小结

1.2 入门程序剖析

为什么一个main方法就将web应用启动了?
图9 入门程序剖析1
图10 入门程序剖析2

2. HTTP协议

HTTP协议

2.1 HTTP-请求协议

HTTP协议--请求数据格式
图12 http请求数据格式
常见的http请求头
Host 请求的主机名
User-Agent 浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0 ... Chrome/79,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...) like Gecko
Accept 表示浏览器能接收的资源类型,如text/,image/或者/表示所有;
Accept-Language 表示浏览器偏好的语言,服务器可以据此返回不同语言的网页;
Accept-Encoding 表示浏览器可以支持的压缩类型,例如gzip, deflate等。
Content-Type 请求主体的数据类型。
Content-Length 请求主体的大小(单位:字节)。
小结

Http协议中请求数据分为哪几个部分?

图13 http请求小结
HTTP协议-请求数据获取
图14 HTTP协议-请求数据获取
package cn.zjy;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RequestController {

    @RequestMapping("/request")
    public String request(HttpServletRequest request) {
        //1.获取请求方式
        //2.获取请求url地址
        //3.获取请求协议
        //4.获取请求参数-name
        //5.获取请求头-Accept
        return "请求方式:"+request.getMethod()+"<br/>"
                +"请求url地址:"+request.getRequestURL()+"<br/>"
                +"请求协议:"+request.getProtocol()+"<br/>"
                +"请求参数-name:"+request.getParameter("name")+"<br/>"
                +"请求头-Accept:"+request.getHeader("Accept");

    }
}
图15 HTTP协议-请求数据获取验证
小结

HTTP请求数据需要程序员自己解析吗?

如何获取请求数据?

图16 HTTP协议-请求数据获取小结

2.2 HTTP-响应协议

HTTP协议--响应数据格式
图17 HTTP协议--响应数据格式
图18 HTTP协议--重定向(两次请求)
常用的状态码
状态码 描述
1xx 响应中-临时状态码,表示请求已经接收,告诉客户端应该继续请求或者如果它已经完成则忽略它。
2xx 成功-表示请求已经被成功接收,处理已完成。
3xx 重定向-重定向到其他地方;让客户端再发起一次请求以完成整个处理。
4xx 客户端错误-处理发生错误,责任在客户端。如: 请求了不存在的资源、客户端未被授权、禁止访问等。
5xx 服务器错误-处理发生错误,责任在服务端。如:程序抛出异常等。
常用的响应头
类型 描述
Content-Type 表示该响应内容的类型,例如text/html,application/json。
Content-Length 表示该响应内容的长度(字节数)。
Content-Encoding 表示该响应压缩算法,例如gzip。
Cache-Control 指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒。
Set-Cookie 告诉浏览器为当前页面所在的域设置cookie。
最常用的状态码
状态码 描述
200 客户端请求成功。
404 请求资源不存在,URL输入有误,或者网站资源被删除了。
500 服务器发生不可预期的错误。
小结

HTTP响应数据分为几个部分?

响应状态码的分类?

图19 HTTP协议--响应小结
HTTP协议-响应数据设置
图20 HTTP协议--响应数据设置
图21 HTTP协议--响应数据设置
cn/zjy/ResponesController.java
package cn.zjy;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
public class ResponesController {
    /**
     *方式一:HttpServletResponse设置响应数据
     */
    @RequestMapping("/response")
    public void response(HttpServletResponse response) throws IOException {
        //1.设置响应状态码
        response.setStatus(401);
        //2.设置响应头
        response.setHeader("name", "zjyiang");
        //3.设置响应体
        response.getWriter().write("<h1>hello response</h1>");
    }

    /**
     *方式二:ResponseEntity-Spring中提供的方式
     */
    @RequestMapping("/response2")
    public ResponseEntity<String> response2(){
        return ResponseEntity
                . status(401)//响应状态码
                .header("name","Du") //响应头
                .body("<h1>hello response2 </h1>"); //响应体
    }
}
图22 HTTP协议--响应数据设置验证
HTTP协议-响应小结

HTTP响应数据需要程序员自己手动设置吗?

响应状态码、响应头需要我们手动指定吗?

图23 HTTP协议--响应数据设置小结

3. SpringBoot Web案例

图24 SpringBoot Web案例
图25 创建SpringBoot Web案例项目
图26 案例项目添加依赖、静态资源
cn/zjy/pojo/User.java
package cn.zjy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id; 
    private String username; 
    private String password; 
    private String name; 
    private Integer age; 
    private LocalDateTime updateTime; 
}
cn/zjy/controller/UserController.java
package cn.zjy.controller;

import cn.zjy.pojo.User;
import cn.hutool.core.io.IoUtil;
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;

/**
 *用户信息Controller
 */
@RestController
// @Controller->作用:将controller返回值封装为响应数据
// @Controller注解中包含@ResponseBody注解
// @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");
        ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

        //2.解析用户信息,封装为User对象->list集合
        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);
        }).toList();

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

}
图27 项目后台验证、运行验证
图28 springboot-web案例小结

4. 分层解耦

图29 思考:没有分层的问题?
目录

4.1 三层架构

图30 分层之前
图30 三层架构
图32 创建三层架构: service,dao及其impl
cn/zjy/dao/UserDao.java
package cn.zjy.dao;
import java.util.List;

public interface UserDao {
    public List<String> list();
}
cn/zjy/dao/impl/UserDaoImpl.java
package cn.zjy.dao.impl;

import cn.zjy.dao.UserDao;
import cn.hutool.core.io.IoUtil;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class UserDaoImpl implements UserDao {

    public List<String> list() {
        //1.加载并读取文件
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
        return IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
    }
}
cn/zjy/service/UserService.java
package cn.zjy.service;

import cn.zjy.pojo.User;
import java.util.List;

public interface UserService {
    public List<User> list();
}
cn/zjy/service/impl/UserServiceImpl.java
package cn.zjy.service.impl;

import cn.zjy.dao.UserDao;
import cn.zjy.dao.impl.UserDaoImpl;
import cn.zjy.pojo.User;
import cn.zjy.service.UserService;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();

    public List<User> list(){
        //1.调用dao获取数据
        List<String> lines = userDao.list();

        //2.解析数据,封装成对象—-—> 集合
        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);
        }).toList();
        return userList;
    }
}
cn/zjy/controller/UserController.java 添加list2()
    private UserService userService = new UserServiceImpl();
    @RequestMapping("/list2")
    public List<User> list2() {
        //1.调用service,查询用户信息
        List<User> userlist = userService.list();
        //2.响应数据
        return userlist;
    }
图33 三层架构验证
图34 划分为三层架构及其调用关系

为什么要对代码进行拆分?

拆分为了哪三层?每一层的职责是什么?

图35 三层架构小结

4.2 分层解耦

图36 耦合
图37 分层解耦
图38 分层解耦的思路

实现分层解耦的思路是什么?

4.3 IOC & DI入门

图39 Spring分层解耦

① 控制反转(IoC):将Dao 及 Service层的实现类,通过@Component交给IOC容器管理。

② 依赖注入(DI):为Controller 及 Service通过@Autowired注入运行时所依赖的对象。

cn/zjy/dao/impl/UserDaoImpl.java 添加@Component
package cn.zjy.dao.impl;

import cn.zjy.dao.UserDao;
import cn.hutool.core.io.IoUtil;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Component  // @Component->作用:将类交给spring管理 -- 将当前类交给IOC容器管理
public class UserDaoImpl implements UserDao {

    public List<String> list() {
        //1.加载并读取文件
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
        return IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
    }
}
cn/zjy/service/impl/UserServiceImpl.java 添加@Component和@Autowired注解,注释new
package cn.zjy.service.impl;

import cn.zjy.dao.UserDao;
// import cn.zjy.dao.impl.UserDaoImpl;
import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Component  // @Component->作用:将类交给spring管理 -- 将当前类交给IOC容器管理
public class UserServiceImpl implements UserService {
    @Autowired  //应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    private UserDao userDao; // = new UserDaoImpl();

    public List<User> list(){
        //1.调用dao获取数据
        List<String> lines = userDao.list();

        //2.解析数据,封装成对象—-—> 集合
        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);
        }).toList();
        return userList;
    }
}
cn/dzj/controller/UserController.java 添加@Autowired注解,注释new
package cn.dzj.controller;

import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
// import cn.dzj.service.impl.UserServiceImpl;
import cn.hutool.core.io.IoUtil;
import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 *用户信息Controller
 */
@RestController
// @Controller->作用:将controller返回值封装为响应数据
// @Controller注解中包含@ResponseBody注解
// @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");
        ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

        //2.解析用户信息,封装为User对象->list集合
        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);
        }).toList();

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

    @Autowired  //应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    private UserService userService; // = new UserServiceImpl();
    @RequestMapping("/list2")
    public List<User> list2() {
        //1.调用service,查询用户信息
        List<User> userlist = userService.list();
        //2.响应数据
        return userlist;
    }

}
IOC & DI验证
图40 调式:断点检查变量是否生成
图41 分层解耦小结

4.4 IOC详解

图42 IOC注解
注解 说明 位置
@Component 声明bean的基础注解 不属于以下三类时,用此注解
@Controller @Component的衍生注解 标注在控制层类上
@Service @Component的衍生注解 标注在业务层类上
@Repository @Component的衍生注解 标注在数据访问层类上(由于与mybatis整合,用的少)

声明bean的注解有哪几个 ?

注意事项

图43 IOC注解小结

4.5 DI详解

基于@Autowired进行依赖注入的常见方式有如下三种:

①.属性注入

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    //......
}

②.构造函数注入

@RestController
public class UserController {
    private final UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
}

③.setter注入

@RestController
public class UserController {
    private final UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
}
图44 依赖注入的常见方式
cn/dzj/controller/UserController.java 三中常见的依赖注入方式测试
package cn.dzj.controller;

import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
// import cn.dzj.service.impl.UserServiceImpl;
import cn.hutool.core.io.IoUtil;
import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 *用户信息Controller
 */
@RestController
// @Controller->作用:将controller返回值封装为响应数据
// @Controller注解中包含@ResponseBody注解
// @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");
        ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());

        //2.解析用户信息,封装为User对象->list集合
        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);
        }).toList();

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

    //方式一:属性注入
    //@Autowired //自动注入 应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    //private UserService userService; // = new UserServiceImpl();

    //方式二:构造器注入
    //private final UserService userService;
    //@Autowired  //--->如果当前类中只存在一个构造函数,@Autowired可以省略
    //public UserController(UserService userService) {
    //    this.userService = userService;
    //}

    //方式三:setter注入
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    @RequestMapping("/list2")
    public List<User> list2() {
        //1.调用service,查询用户信息
        List<User> userlist = userService.list();
        //2.响应数据
        return userlist;
    }
}
DI详解
图45 依赖注入多个相同类型的bean解决方案

方案一:@Primary

@Primary
@Service
public class UserServiceImpl implements UserService {
    @Override
    public List<User> list(){
        //省略 ……
    }
}

方案二:@Qualifier

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

方案三:@Resource

@RestController
public class UserController {
    @Resource(name = "userServiceImpl")
    private UserService userService;
}
验证
cn/dzj/service/impl/UserServiceImpl1.java 添加 // @Primary和id+100
package cn.dzj.service.impl;

import cn.dzj.dao.UserDao;
import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

// @Component // @Component->作用:将类交给spring管理 -- 将当前类交给IOC容器管理
// @Primary
@Service
public class UserServiceImpl1 implements UserService {
    @Autowired  //应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    private UserDao userDao; // = new UserDaoImpl();

    public List<User> list(){
        //1.调用dao获取数据
        List<String> lines = userDao.list();

        //2.解析数据,封装成对象—-—> 集合
        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+100, username, password, name, age, updateTime);
        }).toList();
        return userList;
    }
}
cn/dzj/service/impl/UserServiceImpl2.java 添加id+200
package cn.dzj.service.impl;

import cn.dzj.dao.UserDao;
import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

// @Component // @Component->作用:将类交给spring管理 -- 将当前类交给IOC容器管理
@Service
public class UserServiceImpl1 implements UserService {
    @Autowired  //应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    private UserDao userDao; // = new UserDaoImpl();

    public List<User> list(){
        //1.调用dao获取数据
        List<String> lines = userDao.list();

        //2.解析数据,封装成对象—-—> 集合
        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+200, username, password, name, age, updateTime);
        }).toList();
        return userList;
    }
}
cn/dzj/service/impl/UserServiceImpl3.java 添加id+300
package cn.dzj.service.impl;

import cn.dzj.dao.UserDao;
import cn.dzj.pojo.User;
import cn.dzj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

// @Component // @Component->作用:将类交给spring管理 -- 将当前类交给IOC容器管理
@Service
public class UserServiceImpl1 implements UserService {
    @Autowired  //应用程序运行时,会自动的查询该类型的bean对象,并赋值给该成员变量
    private UserDao userDao; // = new UserDaoImpl();

    public List<User> list(){
        //1.调用dao获取数据
        List<String> lines = userDao.list();

        //2.解析数据,封装成对象—-—> 集合
        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+300, username, password, name, age, updateTime);
        }).toList();
        return userList;
    }
}
cn/dzj/controller/UserController.java 依赖注入处局部修改如下测试
    private UserService userService;
    // 方案1 @Autowired不变 UserServiceImpl1添加@Primary使该类生效
    // @Autowired

    // 方案2 @Autowired不变 UserServiceImpl1去掉@Primary使该类失效 使用@Qualifier注解
    //@Qualifier("userServiceImpl2")

    // 方案3 @Autowired去掉 UserServiceImpl1去掉@Primary使该类失效 使用@Resource注解
    //@Resource(name = "userServiceImpl3")
图46 依赖注入验证
依赖注入小结

①依赖注入的注解

②@Resource 与 @Autowired区别 ?

图47 依赖注入小结

①②③④⑤⑥⑦⑧⑨⑩


在 Spring Boot 中,Spring MVC 的核心内容可简明概括为:

  1. 核心组件:DispatcherServlet(前端控制器,统一分发请求)、Controller(处理请求的控制器)、HandlerMapping(映射请求到处理器)、HandlerAdapter(执行处理器)、ViewResolver(解析视图)。
  2. 请求处理流程:请求经 DispatcherServlet 转发,通过 HandlerMapping 找到对应 Controller,处理器执行后返回 ModelAndView,再由 ViewResolver 解析视图并渲染响应。
  3. 常用注解:@Controller(标识控制器)、@RestController(组合 @Controller 和 @ResponseBody,返回数据而非视图)、@RequestMapping(映射请求路径 / 方法)、@GetMapping/@PostMapping 等(特定 HTTP 方法映射)、@RequestParam/@PathVariable(获取请求参数)、@RequestBody(接收 JSON 请求体)等。
  4. 视图支持:整合 Thymeleaf、JSP 等视图技术,也常用于构建 RESTful API(返回 JSON/XML 数据)。
  5. 扩展机制:包括拦截器(HandlerInterceptor)、全局异常处理(@ControllerAdvice + @ExceptionHandler)等。

在 Spring Boot 中,包含的 Spring 核心内容可简明概括为:

  1. 核心容器:IoC(控制反转)容器、Bean 管理(依赖注入、生命周期管理等),基于@Component@Autowired等注解。
  2. AOP:面向切面编程,支持事务管理、日志、权限等横切逻辑,通过@Aspect@Transactional等实现。
  3. 数据访问:整合 Spring JDBC、ORM(如与 Hibernate、MyBatis 适配),提供统一的数据访问抽象。
  4. 事务管理:声明式事务支持,通过注解或配置管理事务边界。
  5. 安全框架:集成 Spring Security,提供认证、授权等安全功能。
  6. 测试支持:基于 Spring Test,支持单元测试、集成测试。
  7. 其他基础功能:事件机制、资源管理、国际化等。

Spring Boot 本质是对 Spring 框架的简化封装,保留其核心功能并通过自动配置减少配置工作量。


返回