目录
在Web开发中有两种主要的结构,称为模式一(ModeI)和模式二(Mode II)
8.1 WEB开发模式一(Model 1)
概述
WEB开发模式一,通常称为Model 1或Traditional Web Application Model,是一种较为简单的Web应用程序设计架构。在这种模式下,大部分逻辑和数据处理工作直接在服务器端的JSP页面内完成。JSP(JavaServer Pages)作为动态网页技术,允许在HTML代码中嵌入Java代码,从而实现动态内容的生成。Model 1的特点和工作流程如下:
特点
- 高度耦合:JSP页面同时承担用户界面渲染、业务逻辑处理和数据访问任务,导致视图、业务逻辑和数据访问层紧密耦合。
- 简单易用:对于小型、需求简单的项目,Model 1因其结构简单、开发快速而受到青睐。
- 不利于扩展和维护:随着应用规模的增长和复杂性的提升,代码变得难以管理,修改一处可能导致多处受到影响。
- 不利于分工合作:开发人员需要具备前端和后端技能,角色界限模糊,不利于团队成员的专业化分工。
工作流程
- 客户端请求:用户通过浏览器向服务器发送HTTP请求。
- JSP页面接收请求:请求到达服务器,由JSP引擎解析请求并执行JSP页面内的Java代码。
- 业务逻辑处理:JSP页面内嵌的Java代码直接处理业务逻辑,可能涉及数据查询、计算、逻辑判断等。
- 数据访问:有时使用JavaBean封装数据访问逻辑,但这些JavaBean往往直接在JSP页面内实例化和调用,没有明确的分层。
- 视图渲染:处理完业务逻辑后,JSP页面动态生成HTML内容,将结果返回给客户端。
Mode I的处理情况分为两种
完全JSP模式
- 用户发出的请求(request),交给JSP页面进行处理,为了开发快速与便利,通常都会将显示层(PresentationLayer)和逻辑运算层(Business Logic Layer)全部都写在JSP页面中
使用JSP + JavaBean模式
- 将显示操作都写入JSP页中,而业务层都写成JavaBean形式,将程序代码封装成组件,这样JavaBean将负责大部分的数据处理。例如执行数据库操作等(类似于DAO),再将数据处理后的结果,返回至JSP页上显示
Model 1 模型图
8.2 WEB开发模式二(Model 2)
概述
WEB开发模式二,也称作Model 2或MVC(Model-View-Controller)架构,是一种更成熟、结构化更强的Web应用程序设计模式。它严格分离了视图、业务逻辑和数据访问层,提高了代码的可维护性、可扩展性和团队协作效率。Model 2的特点和工作流程如下:
特点
- 分离关注点:将应用程序划分为模型(Model)、视图(View)和控制器(Controller)三个核心组件,各司其职,降低耦合度。
- 可维护性:由于职责明确,各层代码独立,修改一处不影响其他部分,易于调试和维护。
- 可扩展性:易于添加新功能、更换视图技术或数据库系统,不影响整体架构。
- 利于团队协作:开发人员可以根据专长专注于前端、后端或数据访问层面的工作。
工作流程
- 客户端请求:用户通过浏览器向服务器发送HTTP请求。
- 控制器(Controller)接收请求:请求首先到达控制器(如Spring MVC中的
@Controller
类或Struts中的Action类),控制器负责解析请求参数、调用适当的业务逻辑方法。 - 模型(Model)处理业务逻辑:控制器调用模型(如Service层或DAO层)处理业务逻辑,模型通常包含业务规则、数据验证和数据访问操作。
- 数据访问:模型中的数据访问对象(DAO)使用JDBC、ORM框架(如Hibernate、JPA)等技术访问数据库,执行CRUD操作。
- 视图(View)渲染:控制器根据业务逻辑处理结果选择合适的视图,并将模型数据传递给视图。视图可以是JSP、Thymeleaf、FreeMarker等模板引擎生成的HTML,也可以是JSON、XML等数据格式供AJAX调用。
- 响应客户端:渲染后的视图(HTML或其他格式)返回给客户端浏览器展示。
Model 2 模型图
对比
模式 | 特点 | 适用场景 |
---|---|---|
Model 1 | 简单快速,高度耦合 | 小型、需求简单、短期项目 |
Model 2 (MVC) | 分离关注点,可维护性强 | 大型、复杂、长期项目,专业团队开发 |
综上所述,WEB开发模式一是早期Web开发中常见的一种简化结构,适用于小规模、需求简单的项目。而随着Web应用复杂度的提高和开发实践的发展,Model 2(MVC)模式因其良好的分离性和可维护性,成为现代Web开发的标准架构。在实际项目中,应根据项目规模、需求复杂度和团队能力等因素选择合适的开发模式。
8.3 Spring MVC介绍
Spring MVC 是Spring框架提供的一个用于构建Web应用程序的模块,它实现了Model-View-Controller(MVC)设计模式。Spring MVC以其轻量级、高度可配置性、与Spring生态系统的深度集成以及对RESTful API的良好支持而广受欢迎。
- 封装数据处理数据的模型(Model)
模型所表示的是具体做工作的部分,并对应用所要解决的实际问题进行建模,即保存数据的状态
- 负责展示数据的视图(View)
视图是模型的表示,用户可以看到视图并与之交互,即显示页面
- 控制程序流转的控制器(Controller)
控制器是应用中对用户命令做出响应的部分,即取得表单数据、调用业务逻辑、转向指定的页面等
特点
- 松散耦合:Spring MVC遵循MVC架构,将应用程序划分为模型(Model)、视图(View)和控制器(Controller),降低了各组件间的耦合度。
- 灵活性:支持多种视图技术(如JSP、Thymeleaf、FreeMarker等)和多种数据绑定方式,可根据项目需求灵活选择。
- 强大配置:基于Java配置和注解的配置方式,使得开发者可以方便地定制化请求映射、数据验证、异常处理等行为。
- RESTful支持:内置对RESTful API的设计和实现支持,便于构建现代Web服务。
- 国际化与本地化:内置对多语言和区域设置的支持,轻松实现全球化应用程序。
- 测试友好:由于其面向接口和依赖注入的设计,Spring MVC应用易于进行单元测试和集成测试。
优势
- 与Spring生态集成:无缝集成Spring IoC容器,利用Spring的依赖注入、事务管理、AOP等功能,简化开发。
- 强大的拦截器机制:可以定义全局或特定请求的拦截器,进行预处理、后处理、权限检查、日志记录等工作。
- 数据验证与格式化:内置对请求参数的校验和格式化支持,可通过注解实现表单数据的自动验证。
- 异常处理:提供了统一的异常处理机制,可定制错误页面和返回错误信息的格式。
- 可扩展性:开放的架构允许开发者自定义各个组件,适应各种复杂的业务需求。
8.4 Spring MVC主要组件
1. DispatcherServlet
前端控制器(Front Controller):DispatcherServlet作为Spring MVC的核心组件,充当所有HTTP请求的入口点。它继承自javax.servlet.http.HttpServlet
,并注册在web.xml或使用Spring Boot的自动配置方式部署为Servlet容器(如Tomcat)的一部分。其主要职责包括:
-
请求分发:根据请求信息(如URL、HTTP方法、请求头等),DispatcherServlet通过查询已配置的
HandlerMapping
来决定哪个Handler
(通常是Controller
)应该处理该请求。 -
控制器方法调用:通过
HandlerAdapter
与实际的Controller交互,执行Controller中对应的方法,并处理其返回结果。 -
模型与视图管理:处理Controller返回的
ModelAndView
对象,其中包含业务逻辑处理后的模型数据和视图名称。根据视图名称,通过ViewResolver
找到具体的视图实现,并将模型数据绑定到视图中进行渲染。 -
异常处理:捕获Controller或处理过程中抛出的异常,通过
HandlerExceptionResolver
进行异常转换和适当地响应给客户端。 -
拦截器链管理:调度配置的
Interceptor
(拦截器)在请求处理前后执行额外的预处理和后处理逻辑,如身份验证、日志记录、数据过滤等。 -
资源处理:对于静态资源请求,DispatcherServlet通常会配置为忽略或通过专门的处理器(如Spring的
ResourceHttpRequestHandler
)来处理。
2. HandlerMapping
处理器映射器:负责建立请求与Controller方法之间的映射关系。Spring MVC提供了多种HandlerMapping
实现,如:
-
RequestMappingHandlerMapping:基于注解的映射,如
@RequestMapping
、@GetMapping
、@PostMapping
等。 -
BeanNameUrlHandlerMapping:基于Controller类或方法bean名称与URL路径的直接映射。
-
SimpleUrlHandlerMapping:基于XML或Java配置中的URL路径与Controller的显式映射。
HandlerMapping组件在接收到请求时,会根据其内部的映射规则查找匹配的HandlerExecutionChain
,该链包含具体的Handler
(即Controller)和可能的拦截器列表。
3. Controller(处理器)
业务逻辑处理:Controller是处理业务逻辑的组件,通常是一个Java类,通过注解如@Controller
、@RestController
标识。Controller中的方法(处理程序)负责处理特定的HTTP请求,执行业务逻辑,如数据验证、数据库操作、调用服务等,并准备响应数据。
响应数据的返回方式有以下几种:
-
ModelAndView:返回包含模型数据(
Model
)和视图名称(View
)的对象,指示DispatcherServlet如何渲染响应。 -
Redirect/Forward:返回一个特殊的
RedirectView
或View
对象,实现重定向或请求转发。 -
@ResponseBody /
ResponseEntity
:直接将方法返回值序列化为HTTP响应体,适用于RESTful API场景,无需视图渲染。 -
异步请求支持:通过
DeferredResult
、Callable
或WebAsyncTask
支持异步处理请求,允许长时间运行的任务在后台执行,同时保持与客户端的连接。
4. HandlerAdapter
适配器模式:HandlerAdapter负责调用Controller中的方法,并将方法的返回值转换为DispatcherServlet能够理解的格式。Spring MVC提供了多个HandlerAdapter实现,以适应不同类型的Controller(如基于注解的、实现特定接口的)。Adapter确保Controller与Servlet API解耦,使Controller专注于业务逻辑,而不必关心Servlet API的具体细节。
5. ModelAndView
模型与视图封装:ModelAndView对象封装了Controller处理请求后的模型数据(键值对集合)和视图名称。模型数据将在视图渲染阶段被填充到视图中,用于动态生成响应内容。视图名称将被ViewResolver用来查找和实例化实际的视图实现。
6. ViewResolver
视图解析:ViewResolver负责将Controller返回的视图名称转换为实际的View
对象。Spring MVC支持多种视图技术,如JSP、Thymeleaf、FreeMarker、Velocity等,每种技术都有对应的ViewResolver实现。当ViewResolver找到匹配的视图后,会将Controller传递的模型数据绑定到视图中,并最终生成HTML或其他格式的响应内容。
7. Interceptors(拦截器)
预处理与后处理:拦截器是在请求到达Controller方法之前或之后执行额外逻辑的组件。它们通常用于实现诸如身份验证、权限检查、日志记录、通用数据预处理(如添加默认值、统一响应包装)等跨切面的需求。拦截器通过实现HandlerInterceptor
接口或继承WebRequestInterceptor
来创建,并在Spring配置中注册到DispatcherServlet上。
8. Validation(验证器)
数据校验:Spring MVC支持对请求参数或模型属性进行数据验证,基于JSR-303/JSR-349 Bean Validation标准(如Hibernate Validator)。通过在模型对象的属性上使用注解(如@NotNull
、@Size
、@Pattern
等),Spring MVC可以在数据绑定过程中自动执行验证,并在验证失败时产生适当的错误消息。验证结果可以通过BindingResult
对象在Controller中访问,以便进行错误处理和反馈。
9. LocaleResolver & ThemeResolver
国际化与主题支持:这两个组件分别用于解析和设置客户端的地域偏好(Locale)和应用主题(Theme),以支持多语言和外观定制。例如,CookieLocaleResolver
可以根据客户端的cookie来确定应使用的语言和地区设置。
综上,Spring MVC通过这些主要组件协同工作,形成了一套高效、灵活且可扩展的Web应用程序开发框架,能够应对各种复杂的企业级Web应用需求。
8.5 Spring MVC处理流程
在MVC设计模式中,最关键的部分就是要使用RequestDispatcher接口,因为显示内容都是通过此接口保存到JSP页面上进行显示的
简化流程
- 将URL映射到Java类或方法
- 封装用户提交的数据
- 处理用户请求,调用相关的业务处理,封装响应数据
- 将响应的数据进行渲染和呈现
具体流程
1.客户端浏览器向前端控制器(DispatcherServlet)发出请求
2.前端控制器(DispatcherServlet)接收请求后根据配置到相应的Handler中进行处理,调用处理器映射器(HandlerMapping)获取数据和视图后响应结果
3.理器映射器(HandlerMapping),根据请求的URL来查找后端处理器(Handler),将访问路径和对应的Handler存储为映射关系,返回处理器对象(Handler)和处理器拦截器对象(HandlerInterceptor)给前端控制器(DispatcherServlet)
4.前端控制器(DispatcherServlet)拿到信息后调用处理器适配器(HandlerAdapter),找到真正的Handler执行请求响应和对应的Handler信息,将结果即Model和View返回给处理器适配器(HandlerAdapter)
5.处理器适配器(HandlerAdapter)将Model和View对象返回给前端控制器(DispatcherServlet)
6.前端控制器(DispatcherServlet)在拿到Model和View对象之后发给视图解析器(ViewResolver)
7.视图解析器(ViewResolver)将Model和View对象进行解析,生成成真正的视图对象(View),将View对象返回给前端控制器(DispatcherServlet)
8.前端控制器(DispatcherServlet)拿到View对象后,根据解析结果调用具体的视图,即将返回的Model数据填充到视图(View)中,渲染好的JSP页面会呈现给用户
8.6 Spring MVC的HTTP请求方法
注解 | HTTP请求方法 |
---|---|
@GetMapping | POST |
@PostMapping | GET |
@PutMapping | PUT |
@PatchMapping | PATCH |
@DeleteMapping D | ELETE |
@RequestMapping | 可用于以上五种请求,需在method属性中指定 |
当然可以,以下是关于Spring MVC的HTTP请求方法更详细的说明:
Spring MVC对HTTP请求方法的支持
Spring MVC全面支持HTTP 1.1定义的多种请求方法,这些方法体现了REST(Representational State Transfer)架构风格的核心原则,即资源操作通过特定的HTTP方法与URI关联。下面对每种请求方法进行详细阐述,并给出Spring MVC中如何处理它们的示例:
1. GET
目的:从服务器检索指定资源的状态。通常用于读取数据,不会改变服务器状态。
使用场景:
- 获取用户信息、文章详情、商品列表等。
- 实现资源的缓存,因为GET请求的结果被认为是幂等的(多次执行相同请求应得到相同结果)。
Spring MVC示例:
@GetMapping("/users/{id}")
public User getUserDetails(@PathVariable Long id) {
return userService.getUserById(id);
}
在这个例子中,@GetMapping
注解表示该方法处理针对/users/{id}
路径的GET请求。@PathVariable
用于捕获URL中的动态部分({id}
),并将其作为参数传递给方法。
2. POST
目的:向指定资源提交数据,请求被处理后可能会创建新的资源或触发资源状态的更改。
使用场景:
- 创建新用户、发表评论、提交订单等涉及数据添加的操作。
Spring MVC示例:
@PostMapping("/users")
public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
userService.createUser(user);
return ResponseEntity.created(URI.create("/users/" + user.getId())).build();
}
这里,@PostMapping
注解指示该方法处理POST请求到/users
路径。@RequestBody
将请求体中的JSON或XML数据自动转换为User
对象。@Valid
用于启用JSR-303/JSR-349数据校验。成功创建用户后,返回一个带有创建资源的URI的201 Created
响应。
3. PUT
目的:替换指定资源的内容。请求体应包含完整的更新数据,如果资源不存在,服务器可能会创建它。
使用场景:
- 更新用户资料、修改文章内容、替换整个产品信息等。
Spring MVC示例:
@PutMapping("/users/{id}")
public ResponseEntity<Void> updateUser(@PathVariable Long id, @Valid @RequestBody User updatedUser) {
userService.updateUser(id, updatedUser);
return ResponseEntity.noContent().build();
}
使用@PutMapping
注解的方法处理PUT请求到/users/{id}
。updatedUser
参数包含完整的更新数据。成功更新后,返回204 No Content
响应,表明请求已成功处理,无须返回任何实体内容。
4. DELETE
目的:请求服务器删除指定的资源。
使用场景:
- 删除用户账户、移除文章、取消订单等。
Spring MVC示例:
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
@DeleteMapping
注解的方法处理DELETE请求到/users/{id}
。成功删除用户后,同样返回204 No Content
响应。
5. PATCH
目的:对指定资源进行部分更新。请求体仅包含需要更新的字段及其新值,而非整个资源的完整表示。
使用场景:
- 修改用户部分信息(如仅更新邮箱地址或电话号码)、更新文章的部分元数据等。
Spring MVC示例:
@PatchMapping("/users/{id}")
public ResponseEntity<User> patchUser(@PathVariable Long id, @RequestBody JsonPatch patch) {
User updatedUser = userService.patchUser(id, patch);
return ResponseEntity.ok(updatedUser);
}
这里使用@PatchMapping
注解处理PATCH请求。JsonPatch
对象包含了要应用于用户资源的JSON Patch操作。成功部分更新后,返回包含更新后用户信息的200 OK
响应。
6. HEAD
目的:与GET类似,但仅要求服务器返回响应头部信息,无响应体。用于检查资源是否存在、获取元数据或检查条件等,节省带宽。
使用场景:
- 检查资源的最后修改时间、验证ETag、预检缓存有效性等。
Spring MVC示例:
@HeadMapping("/users/{id}")
public void headUser(@PathVariable Long id) {
// 在此处可以检查用户是否存在、设置响应头等,但不返回响应体
}
尽管Spring框架并未提供@HeadMapping
注解,但可以通过自定义HandlerMethodArgumentResolver
和HandlerMethodReturnValueHandler
来支持HEAD请求。通常,这类方法无需返回值,只需设置响应头即可。
7. OPTIONS
目的:询问服务器指定URL支持哪些HTTP方法,用于跨域资源共享(CORS)的预检请求,也可以用于发现API功能。
使用场景:
- 实现CORS时,浏览器会自动发送OPTIONS请求以确定实际请求是否允许。
- API客户端查询某个资源支持的操作列表。
Spring MVC示例:
@OptionsMapping("/users/{id}")
public ResponseEntity<HttpHeaders> optionsUser() {
HttpHeaders headers = new HttpHeaders();
headers.setAllow(Arrays.asList(HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE));
return new ResponseEntity<>(headers, HttpStatus.OK);
}
尽管Spring框架未提供@OptionsMapping
注解,但可以通过自定义HandlerMethodArgumentResolver
和HandlerMethodReturnValueHandler
来支持OPTIONS请求。此示例中,响应头Allow
字段列出了对/users/{id}
资源支持的HTTP方法。
Spring MVC通过丰富的注解支持,使得开发者能够轻松地处理各种HTTP请求方法,实现符合RESTful原则的Web服务。每个请求方法对应特定的资源操作,有助于构建清晰、语义化的API接口。