先修知识:依赖注入,反转控制,生命周期
IDEA快捷键
Ctrl + Alt+m:提取方法,设置trycatch
通用快捷键:
Ctrl + F
:在当前文件中查找文本。Ctrl + R
:在当前文件中替换文本。Ctrl + Z
:撤销上一步操作。Ctrl + Y
:删除当前行或选中的行。Ctrl + D
:复制当前行或选中的内容,并插入到光标下方。Ctrl + W
:递进式选择代码块,连续按可扩展选中范围。Ctrl + E
:显示最近打开的文件列表。Ctrl + N
:根据类名查找类文件。Ctrl + Shift + N
:根据文件名查找文件。Ctrl + Alt + L
:格式化代码。Ctrl + Alt + O
:优化导入的类。Ctrl + Alt + T
:包裹选中的代码块。Ctrl + Alt + B
:跳转到方法或变量的实现处。Ctrl + Alt + F7
:显示当前类或方法的使用情况。Ctrl + Alt + S
:打开系统设置。Ctrl + Alt + F1
:在项目视图中定位当前文件。Ctrl + Alt + F12
:切换到当前文件的工具窗口。
编辑相关:
Ctrl + /
:对当前行或选中的代码进行行注释或取消注释。Ctrl + Shift + /
:对当前代码块进行块注释或取消注释。Ctrl + Shift + J
:将下一行合并到当前行。Ctrl + Shift + U
:切换选中内容的大小写。Ctrl + Shift + V
:从剪贴板历史中粘贴内容。Ctrl + Shift + I
:快速查看光标所在的定义。Ctrl + Shift + F
:在项目中查找文本。Ctrl + Shift + R
:在项目中替换文本。Ctrl + Shift + A
:查找并执行操作。
调试相关:
F7
:进入方法内部。F8
:跳过当前行。F9
:恢复程序运行。Shift + F7
:智能步入。Shift + F8
:跳出当前方法。Alt + F8
:评估表达式。Ctrl + F8
:切换断点。Ctrl + Shift + F8
:查看断点。
导航相关:
-
Ctrl + B
或Ctrl + 鼠标左键
:跳转到方法或变量的定义处。 -
Ctrl + Alt + 左/右箭头
:在编辑器中前进或后退。 -
Ctrl + G
:跳转到指定行号。 -
Ctrl + F12
:显示文件结构。 -
Ctrl + Shift + F12
:最大化或恢复编辑器窗口。 -
Ctrl + Tab
:在打开的文件之间切换。 -
Ctrl + Shift + Tab
:反向切换打开的文件。 -
Ctrl + Alt + F1
:在项目视图中定位当前文件。 -
Ctrl + Alt + F12
:切换到当前文件的工具窗口。 -
IntelliJ IDEA 常用快捷键讲解(Win + Linux)
-
IDEA快捷键大全(Windows)
-
IDEA Windows + Mac 快捷键(全)
http请求的组成
HTTP 请求是客户端(如浏览器、APP)向服务器发送数据的一种规范格式,由 请求行、请求头、空行、请求体 四部分组成。以下是详细内容和示例:
一、HTTP 请求的组成
1. 请求行(Request Line)
- 格式:
请求方法 + URL + HTTP版本
- 示例:
GET /api/users?id=123 HTTP/1.1 POST /api/login HTTP/1.1
- 核心字段:
字段 说明 请求方法 GET
(查询)、POST
(提交)、PUT
(更新)、DELETE
(删除)等。URL 资源路径,可能包含查询参数(如 ?id=123
)。HTTP 版本 通常为 HTTP/1.1
或HTTP/2
。
2. 请求头(Request Headers)
-
格式:
键: 值
-
常见请求头:
请求头 说明 Host
目标服务器域名(如 Host: example.com
)。User-Agent
客户端标识(如浏览器、操作系统)。 Content-Type
请求体的数据类型(如 application/json
、text/html
)。Cookie
客户端存储的会话信息。 Authorization
身份验证凭证(如 Bearer token
)。Accept
客户端能接受的响应格式(如 Accept: application/json
)。 -
示例:
Host: api.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Content-Type: application/json
3. 空行(Empty Line)
- 作用:分隔请求头和请求体,必须存在(即使没有请求体)。
- 示例:
(此处是一个空行)
4. 请求体(Request Body)
- 作用:携带客户端提交的数据(如表单、JSON)。
- 适用场景:
POST
、PUT
、PATCH
等需要传递数据的请求。 - 示例(JSON 格式):
{ "username": "deepseek", "password": "123456" }
二、HTTP 请求示例
1. GET 请求
GET /search?q=http+request HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html
Cookie: session_id=abc123
(空行)
2. POST 请求(表单提交)
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=deepseek&password=123
3. POST 请求(JSON 数据)
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 56
{
"name": "DeepSeek",
"email": "contact@deepseek.com"
}
三、关键总结
组成部分 | 内容 | 示例或说明 |
---|---|---|
请求行 | 方法 + URL + HTTP 版本 | GET /index.html HTTP/1.1 |
请求头 | 客户端和服务器的元数据 | Content-Type: application/json |
空行 | 分隔请求头和请求体 | 必须存在! |
请求体 | 提交的数据(可选) | POST 请求的 JSON、表单数据等。 |
四、注意事项
-
GET 与 POST 的区别
- GET:数据通过 URL 查询参数传递(长度有限制)。
- POST:数据通过请求体传递(支持更大数据量)。
-
Content-Type 的重要性
- 服务器根据
Content-Type
解析请求体数据。 - 常见值:
application/json
:JSON 格式。application/x-www-form-urlencoded
:表单数据(键值对)。multipart/form-data
:文件上传。
- 服务器根据
-
无请求体的情况
GET
、HEAD
、DELETE
等请求通常没有请求体。
spring与http
HTTP请求与Spring框架的关联可以通过其组成部分逐一对应到Spring的处理机制上,以下是详细的解析:
一、HTTP请求的组成
1. 请求行(Request Line)
- 组成:
方法 + URI + HTTP版本
示例:GET /api/users HTTP/1.1
- 关键元素:
- 方法:GET、POST、PUT、DELETE等。
- URI:资源路径,可能包含查询参数(如
/users?id=1
)。 - 协议版本:如HTTP/1.1或HTTP/2。
2. 请求头(Headers)
- 作用:传递元数据,如内容类型、认证信息等。
- 常见头字段:
Content-Type
:请求体格式(如application/json
)。Authorization
:认证令牌(如JWT)。User-Agent
:客户端信息。Accept
:客户端期望的响应格式。
3. 请求体(Body)
- 适用方法:POST、PUT、PATCH等。
- 数据格式:
- 表单数据(
application/x-www-form-urlencoded
)。 - JSON/XML(
application/json
)。 - 文件上传(
multipart/form-data
)。
- 表单数据(
二、Spring框架如何处理HTTP请求
1. 入口:DispatcherServlet
- Spring MVC的核心控制器,接收所有HTTP请求并分发给对应的处理器(Controller)。
- 配置:在
web.xml
或通过WebApplicationInitializer
注册。
2. 映射请求到Controller
- 注解驱动:
@Controller
:标记类为请求处理器。@RequestMapping
:定义URI映射(可细化到@GetMapping
、@PostMapping
等)。
@RestController @RequestMapping("/api") public class UserController { @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { // 处理逻辑 } }
3. 参数绑定
- URL参数:
@RequestParam
:获取查询参数。
@GetMapping("/users") public List<User> getUsers(@RequestParam(required = false) String name) { ... }
- 路径变量:
@PathVariable
:绑定URI中的变量。
@GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { ... }
- 请求体:
@RequestBody
:将JSON/XML反序列化为Java对象。
@PostMapping("/users") public User createUser(@RequestBody User user) { ... }
- 请求头:
@RequestHeader
:获取特定请求头。
@GetMapping("/info") public String getInfo(@RequestHeader("User-Agent") String userAgent) { ... }
- Cookie和Session:
@CookieValue
:获取Cookie值。HttpSession
:直接注入Session对象。
4. 处理请求体数据
- 表单数据:
- 自动绑定到POJO或通过
@RequestParam
获取。
- 自动绑定到POJO或通过
- JSON/XML:
- 使用
@RequestBody
+HttpMessageConverter
(如Jackson
库)反序列化。
- 使用
- 文件上传:
MultipartFile
类型接收上传文件。
@PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { ... }
5. 生成响应
- 直接返回对象:
@RestController
或@ResponseBody
自动序列化返回值为JSON/XML。
- 自定义响应:
ResponseEntity
:控制状态码、响应头、响应体。
@GetMapping("/notfound") public ResponseEntity<User> handle404() { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); }
- 视图渲染:
- 返回视图名(如
return "home";
),由ViewResolver
解析为HTML页面。
- 返回视图名(如
6. 处理异常
@ExceptionHandler
:在Controller内处理特定异常。@ControllerAdvice
:全局异常处理。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(404).body(ex.getMessage());
}
}
三、Spring与HTTP请求的关联示例
1. 处理RESTful请求
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.created(URI.create("/api/users/" + savedUser.getId())).body(savedUser);
}
}
2. 文件上传
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
String fileName = file.getOriginalFilename();
// 保存文件到磁盘
return "上传成功: " + fileName;
}
return "上传失败";
}
3. 内容协商(返回不同格式)
@GetMapping(value = "/data", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public Data getData() {
return dataService.getData();
}
四、关键组件支撑
HandlerMapping
:将请求映射到Controller方法。HandlerAdapter
:执行Controller方法并处理参数绑定。ViewResolver
:解析视图名称到具体页面(如JSP、Thymeleaf)。HttpMessageConverter
:处理请求/响应的序列化与反序列化(如JSON ↔ Java对象)。Interceptor
:在请求处理前后执行逻辑(如日志、鉴权)。
总结
- HTTP请求的每一部分(方法、URI、头、体)均在Spring中有对应处理机制。
- Spring通过注解和组件(如
@GetMapping
、@RequestBody
、DispatcherServlet
)将HTTP请求解构并映射到Java方法。 - 开发者关注业务逻辑,Spring处理底层HTTP协议细节(如参数绑定、内容协商、状态码管理)。
spring和servlet
Spring 框架与 Servlet 技术是 基础与扩展 的关系。Servlet 是 Java EE 的底层规范,负责处理 HTTP 请求和响应;而 Spring(特别是 Spring MVC)是基于 Servlet 构建的高层框架,通过封装和抽象简化了 Web 开发。以下是二者的核心关联和区别:
一、Servlet 是什么?
-
核心角色:
- Servlet 是 Java 的服务器端组件,用于处理 HTTP 请求(
service()
方法)并生成响应。 - 每个 Servlet 需继承
javax.servlet.http.HttpServlet
并重写doGet()
、doPost()
等方法。 - 生命周期由 Servlet 容器(如 Tomcat、Jetty)管理:
init()
→service()
→destroy()
。
- Servlet 是 Java 的服务器端组件,用于处理 HTTP 请求(
-
局限性:
- 手动处理请求参数:需从
HttpServletRequest
中提取参数。 - 视图渲染复杂:需手动拼接 HTML 或集成 JSP。
- 代码冗余:多个 Servlet 需重复编写异常处理、权限校验等逻辑。
- 手动处理请求参数:需从
二、Spring 如何基于 Servlet 工作?
Spring MVC 的底层依赖 Servlet,但通过抽象和封装简化了开发流程,核心组件如下:
1. 核心入口:DispatcherServlet
- 角色:Spring MVC 的前端控制器,接收所有 HTTP 请求并分发给对应的处理器(Controller)。
- 配置:
- 在
web.xml
中定义,拦截指定 URL(如/*
):<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
- 或通过 Java Config 动态注册(Spring Boot 自动完成)。
- 在
2. 关键组件协作流程
HTTP Request → DispatcherServlet → HandlerMapping → Controller → ModelAndView → ViewResolver → HTTP Response
HandlerMapping
:将请求 URL 映射到具体的 Controller 方法(如@RequestMapping
)。HandlerAdapter
:执行 Controller 方法,处理参数绑定(如@RequestParam
、@RequestBody
)。ViewResolver
:解析视图名称(如返回的"home"
)为实际视图(如 JSP、Thymeleaf 模板)。
3. 对比 Servlet 与 Spring MVC 的代码
- 原生 Servlet 处理请求:
public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { String id = req.getParameter("id"); User user = userService.findById(id); resp.setContentType("application/json"); resp.getWriter().write(new Gson().toJson(user)); } }
- Spring MVC 实现相同功能:
@RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") public User getUser(@PathVariable String id) { return userService.findById(id); } }
- 优势:
- 自动参数绑定(无需手动调用
req.getParameter()
)。 - 自动序列化响应(无需手动写 JSON)。
- 依赖注入(
@Autowired
替代手动实例化对象)。
- 自动参数绑定(无需手动调用
三、Servlet 在 Spring 中的直接使用场景
尽管 Spring 封装了大部分 Servlet 细节,但在某些场景仍需直接操作 Servlet API:
1. 访问原生 Servlet 对象
- 在 Controller 方法中注入
HttpServletRequest
或HttpServletResponse
:@GetMapping("/info") public String getInfo(HttpServletRequest request) { String userAgent = request.getHeader("User-Agent"); return "User-Agent: " + userAgent; }
2. 过滤器(Filter)
- 实现
javax.servlet.Filter
,用于日志、权限校验、跨域处理等:@Component public class LogFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { System.out.println("Request URL: " + ((HttpServletRequest) request).getRequestURL()); chain.doFilter(request, response); } }
- 通过
@ServletComponentScan
或配置类注册。
3. 文件上传
- 使用
MultipartFile
(Spring 封装)或直接操作HttpServletRequest
:@PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { // Spring 方式 }
四、Spring Boot 对 Servlet 的进一步简化
Spring Boot 通过内嵌 Servlet 容器(Tomcat/Jetty)和自动配置,进一步隐藏 Servlet 细节:
- 无需
web.xml
:通过@SpringBootApplication
启动应用。 - 自动配置
DispatcherServlet
:默认映射/
,可通过application.properties
调整。 - 简化部署:打包为可执行 JAR(内嵌 Tomcat),无需外部容器。
五、对比总结
维度 | Servlet | Spring MVC |
---|---|---|
角色 | 底层请求处理规范 | 基于 Servlet 的 MVC 框架 |
开发复杂度 | 需手动处理参数、视图、异常 | 通过注解和组件自动处理 |
配置方式 | XML 或 @WebServlet 注解 | 注解驱动(@Controller 、@GetMapping ) |
依赖管理 | 需手动管理 Service/DAO 依赖 | 依赖注入(@Autowired 、@Component ) |
可扩展性 | 需手动实现拦截器、AOP 等 | 提供拦截器(HandlerInterceptor )、AOP |
注解
在 Spring 框架中,注解(Annotation) 和 Bean 是核心概念,二者紧密结合,共同实现依赖注入(DI)和面向切面编程(AOP)。以下是它们的详细解析及关联:
一、什么是 Bean?
Bean 是 Spring 容器管理的对象,是 Spring 应用的构建单元。
- 特点:
- 由 Spring IoC(控制反转)容器实例化、装配和管理。
- 默认是单例(Singleton)模式,但支持其他作用域(如 Prototype)。
- 通过依赖注入与其他 Bean 协作。
二、注解在 Bean 管理中的作用
注解简化了 Bean 的定义、装配和配置过程,替代了传统的 XML 配置方式。
1. 定义 Bean 的注解
以下注解标记类为 Spring Bean,并交由容器管理:
(1)通用注解
-
@Component
标记一个类为通用 Bean,Spring 会自动扫描并注册到容器中。@Component public class UserService { // ... }
-
@Repository
专用于数据访问层(DAO),继承自@Component
,支持数据库异常转换。@Repository public class UserDao { // ... }
-
@Service
专用于业务逻辑层,继承自@Component
,无特殊功能,仅标识语义。@Service public class UserService { // ... }
-
@Controller
专用于 Web 层的控制器,处理 HTTP 请求。@Controller public class UserController { // ... }
-
@Configuration
+@Bean
在 Java 配置类中定义 Bean(适用于第三方库的类或需要动态配置的场景)。@Configuration public class AppConfig { @Bean public DataSource dataSource() { return new HikariDataSource(); } }
(2)高级注解
-
@Scope
指定 Bean 的作用域(如singleton
、prototype
、request
、session
)。@Component @Scope("prototype") public class PrototypeBean { ... }
-
@Lazy
延迟初始化 Bean(默认单例 Bean 在容器启动时初始化)。@Component @Lazy public class LazyBean { ... }
-
@Primary
当存在多个同类型 Bean 时,优先注入标记@Primary
的 Bean。@Component @Primary public class PrimaryService implements MyService { ... }
2. 注入 Bean 的注解
依赖注入(DI)通过以下注解实现:
(1)@Autowired
自动按类型注入 Bean。支持字段、构造方法、Setter 方法注入。
@Component
public class OrderService {
@Autowired
private UserService userService; // 字段注入
@Autowired
public OrderService(UserService userService) { // 构造方法注入
this.userService = userService;
}
}
(2)@Qualifier
指定注入的 Bean 名称(解决多个同类型 Bean 的歧义)。
@Component
public class PaymentService {
@Autowired
@Qualifier("alipayProcessor")
private PaymentProcessor processor;
}
(3)@Resource
按名称注入 Bean(属于 JSR-250 规范,非 Spring 特有)。
@Component
public class OrderService {
@Resource(name = "userService")
private UserService userService;
}
(4)@Value
注入简单类型或配置文件中的值。
@Component
public class EmailService {
@Value("${email.smtp.host}")
private String smtpHost;
}
3. 条件化配置 Bean 的注解
根据条件动态决定是否注册 Bean:
(1)@Conditional
基于自定义条件(实现 Condition
接口)控制 Bean 的注册。
@Bean
@Conditional(DataSourceExistsCondition.class)
public DataSource dataSource() { ... }
(2)Profile 相关注解
通过 @Profile
指定 Bean 在特定环境下生效。
@Bean
@Profile("dev")
public DataSource devDataSource() { ... }
(3)@ConditionalOnProperty
根据配置文件中的属性值决定是否注册 Bean(Spring Boot 特有)。
@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() { ... }
4. Bean 生命周期相关注解
管理 Bean 的初始化和销毁:
-
@PostConstruct
在 Bean 初始化后执行(替代InitializingBean
接口)。@Component public class MyBean { @PostConstruct public void init() { System.out.println("Bean 初始化完成"); } }
-
@PreDestroy
在 Bean 销毁前执行(替代DisposableBean
接口)。@Component public class MyBean { @PreDestroy public void cleanup() { System.out.println("Bean 即将销毁"); } }
三、注解与 Bean 的关联总结
场景 | 注解 | 作用 |
---|---|---|
定义通用 Bean | @Component | 标记类为 Spring 管理的 Bean |
定义分层 Bean | @Repository /@Service /@Controller | 标识不同层次的 Bean(如 DAO、Service、Controller) |
Java 配置类定义 Bean | @Configuration + @Bean | 在配置类中显式定义 Bean |
注入 Bean | @Autowired /@Resource | 自动或按名称注入依赖 |
解决依赖冲突 | @Qualifier | 指定具体注入的 Bean |
配置 Bean 作用域 | @Scope | 定义 Bean 的作用域(如单例、原型) |
条件化注册 Bean | @Conditional /@Profile | 根据条件动态注册 Bean |
生命周期管理 | @PostConstruct /@PreDestroy | 控制 Bean 初始化和销毁行为 |
四、常见问题
-
@Component
vs@Bean
的区别?@Component
标记类为 Bean,由 Spring 扫描并自动注册。@Bean
用于方法,显式定义第三方库的 Bean(需配合@Configuration
)。
-
如何解决多个同类型 Bean 的冲突?
- 使用
@Qualifier
指定名称。 - 使用
@Primary
标记优先注入的 Bean。
- 使用
-
为什么推荐使用构造方法注入?
- 保证依赖不可变(字段注入易被修改)。
- 便于单元测试(无需反射设置字段)。