学习目标
本章将介绍一种经典的Web应用设计模式——MVC设计模式,相对于单纯使用JSP技术完成Web应用程序的开发而言,MVC设计模式使软件项目结构清晰,各层代码分工明确,更适合大体量的应用程序。随后,将学习Controller层的框架产品——Spring MVC技术。(如果没有了解可以去我主页看看 第一至八章的内容来学习)本章将搭建Spring MVC环境,介绍Controller和View之间的映射和参数传递,学习Spring MVC框架的架构及其请求处理流程。
9.1 MVC模式
MVC是指Model—View—Controller(模型-视图-控制器)模式,是开发Web应用程序常用的一种代码分层方式。
MVC这种架构模式就是典型的MVC设计模式,它是软件工程的一种架构模式,会强制性地把系统的输入、处理和输出分开,使系统从功能上形成Model—View—Controller三个基本部分。
- 视图(View): 负责格式化数据并把它们呈现给用户,包括数据展示、数据验证、界面设计等功能。对应组件:JSP或HTML文件。
- 控制器(Controller): 负责接收并转发请求,对请求进行处理后指派视图并将响应结果发送给客户端。对应组件:Servlet。
- 模型(Model): 模型对象拥有最多的处理任务,是应用程序的主体部分,它负责业务逻辑的处理和实际对数据的操作。对应组件:JavaBean(包括处理业务逻辑的Service层、与数据库操作相关的DAO层及贯穿于各层之间的数据模型POJO)。
上面JSP+Servlet+JavaBean的模式就是典型的MVC模式。
下面我将展示一个简单的Java MVC模式示例,使用Spring框架来实现。
- 引入依赖
首先,确保你的项目中引入了Spring MVC的依赖。如果你使用Maven,可以在pom.xml文件中添加类似下面的依赖(版本号可能需要更新):
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.10</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSP API -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
- 模型(Model)
模型是应用程序的数据部分,通常包含业务逻辑和数据的访问。
public class User {
private String name;
private int age;
// 构造器、getter和setter省略
public User(String name, int age) {
this.name = name;
this.age = age;
}
// getter和setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- 视图(View)
视图是用户界面的表示,通常是一个HTML页面或JSP文件。这里我们假设使用JSP。
WEB-INF/views/user.jsp:
<!DOCTYPE html>
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h2>User Profile</h2>
<p>Name: ${user.name}</p>
<p>Age: ${user.age}</p>
</body>
</html>
- 控制器(Controller)
控制器是模型和视图之间的桥梁,处理用户的输入和输出。
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@GetMapping("/user")
public String showUserProfile(Model model) {
User user = new User("John Doe", 30);
model.addAttribute("user", user);
return "user"; // 返回视图的名称,这里对应的是WEB-INF/views/user.jsp
}
}
- 配置Spring MVC
你需要配置Spring MVC以识别控制器并处理请求。这可以通过Java配置或XML配置完成。这里我们假设使用Java配置。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class WebConfig {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
- 部署和运行
将上述代码和配置文件部署到支持Servlet和JSP的Java Web服务器上(如Tomcat),然后启动服务器并访问/user路径以查看结果。
这个简单的例子展示了如何在Java中使用Spring MVC框架实现MVC模式。你可以根据需要扩展模型和控制器,并添加更多的视图
通过MVC设计模式可打造出一个松耦合+高重用性+高可适用性的完美架构,这也是架构设计的目标之一。不过任何一件事都会有利有弊,下面就来总结MVC的优缺点。
优点:
- MVC三个模块相互独立,松耦合架构。
- 多视图共享一个模型,大大提高代码的可重用性。
- 控制器提高了应用程序的灵活性和可配置性。
- 有利于软件工程化管理。
缺点:
- 增加了系统结构和实现的复杂性,不适合小型规模的项目。
- 层与模型之间需要控制器做中间的连接控制,所以效率较低。
9.2 搭建Spring MVC环境
限制MVC框架已经有很多了,如Struts、Webwork等,新兴的MVC构架有SpringMVC、JSF等。Struts1.0是基于Webwork的MVC框架,有很多类的继承关系,耦合性太高。之后又推出了Struts 2.0,但Struts 2.0在处理视图的解析工作时还是存在一些小的不妥之处,因此就产生了Spring MVC框架。
9.2.1 第一个Spring MVC程序
要创建一个基本的Spring MVC程序,你需要配置几个关键部分:Spring MVC的DispatcherServlet、控制器(Controller)、视图(View,通常是JSP文件),以及可能的模型(Model,在Spring MVC中通常通过Controller传递给View的数据来表示)。
下面是一个简单的Spring MVC程序的基本代码结构,包括必要的配置文件和Java类。
- Maven依赖
首先,确保你的pom.xml文件中包含了Spring MVC和其他必要的依赖。
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.10</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSP API -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jstl-impl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
- Spring MVC配置
你可以使用Java配置或XML配置。这里我们使用Java配置。
// WebConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class WebConfig {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
- 控制器(Controller)
// HelloController.java
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello() {
// 返回视图的名称,这里对应的是/WEB-INF/views/hello.jsp
return "hello";
}
}
- 视图(View)
在WEB-INF/views/目录下创建hello.jsp文件。
<!DOCTYPE html>
<html>
<head>
<title>Hello Spring MVC</title>
</head>
<body>
<h2>Hello, Spring MVC!</h2>
</body>
</html>
9.2.2 使用注解开发Spring MVC框架
HandlerMapping意为处理器映射,用于解析前端请求与Controller的映射关系。按照之前的解决方案,需要在配置文件增加如下配置信息:
<bean name="/user" class="com.ktjy.controller.UserController" />
<bean name="/supplier" class="com.ktjy.controller.SupplierController" />
在Spring MVC中,使用注解来开发应用程序是一种非常流行且推荐的方式,因为它减少了XML配置的需要,并使应用程序更加简洁和易于维护。以下是一个使用注解开发的Spring MVC框架的基本Java代码示例。
-
Maven依赖
首先,确保你的pom.xml文件中包含了必要的依赖,与之前的示例类似,但这里不再重复。 -
Spring Boot 启动类
对于使用Spring Boot的Spring MVC应用程序,你将需要一个带有@SpringBootApplication注解的主类来启动Spring应用程序。如果你不使用Spring Boot,则需要一个初始化DispatcherServlet的web.xml或Java配置类(但这里我们专注于使用Spring Boot)。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 控制器
创建一个控制器类,并使用@Controller或@RestController(如果你只返回JSON或XML等,并且不想使用视图)注解。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/")
public String hello(Model model) {
model.addAttribute("message", "Hello, Spring MVC with Annotations!");
return "hello"; // 返回视图的名称
}
}
- 视图
将视图文件(如JSP、Thymeleaf模板等)放在适当的目录下。如果你使用的是Spring Boot,并且配置了spring.mvc.view.prefix和spring.mvc.view.suffix(通常在application.properties或application.yml中),则Spring Boot会自动找到它们。
例如,如果你使用的是JSP,并且你的视图文件位于src/main/resources/templates目录下(注意:对于JSP,你可能需要稍微不同的配置或使用嵌入式Servlet容器支持的特定目录,如Tomcat的webapps目录),你可能需要这样做:
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
但是,请注意,Spring Boot与嵌入式Tomcat通常不直接支持JSP,因为JSP需要编译成Servlet。你可以改用Thymeleaf或FreeMarker等模板引擎,它们与Spring Boot集成得更好。
-
配置文件(可选)
如果你的应用程序需要额外的配置(比如数据库连接、服务器设置等),你可以在application.properties或application.yml文件中添加它们。 -
运行你的应用程序
使用Maven或你的IDE运行DemoApplication类,然后访问http://localhost:8080/(或你配置的任何端口)来查看结果。
注意
- 如果你确实需要使用JSP,并且你的应用是基于Spring Boot的,你可能需要添加对Tomcat的JSP支持的依赖,或者考虑使用不同的视图技术。
- 对于生产环境,你可能还需要配置安全性、日志记录、数据库连接池等。
- Spring Boot极大地简化了Spring MVC应用程序的启动和运行,通过自动配置和减少样板代码来提高开发效率。
9.2.3 Spring MVC框架梳理
在本章前面的课程中,同学们搭建了自己的第一个Spring MVC项目,已经对Spring MVC框架有了初步的认识,接下来再对它的请求处理流程及框架结构做一些深入的学习。
在Spring MVC框架中,虽然Spring Boot简化了大量配置,但了解Spring MVC的基本组件和它们是如何协作的仍然很重要。以下是一个基于Java配置的Spring MVC框架的简要梳理,不涉及Spring Boot的自动配置特性。
- 配置DispatcherServlet
在Spring MVC中,DispatcherServlet是前端控制器,它接收所有的HTTP请求,并将它们分发给相应的控制器处理。在传统的Spring MVC项目中(非Spring Boot),你需要在web.xml中配置DispatcherServlet,但在基于Java配置的项目中,你可以通过实现WebApplicationInitializer接口来配置它。
然而,由于Spring Boot的流行,这里我们主要关注如何通过Java配置来设置Spring MVC,但请注意,在Spring Boot项目中,你通常不需要直接配置DispatcherServlet,因为Spring Boot会自动为你做这件事。
-
配置Spring MVC
在Spring MVC中,你可以通过实现WebMvcConfigurer接口(或其父接口WebMvcConfigurerAdapter,但在Spring 5.0及更高版本中已被弃用)来定制Spring MVC的行为。然而,在Spring Boot项目中,你通常会通过application.properties或application.yml文件以及添加适当的@Bean来配置。 -
控制器(Controller)
控制器是处理HTTP请求的组件。在Spring MVC中,你可以通过创建带有@Controller或@RestController注解的类来定义控制器。@RestController是@Controller和@ResponseBody的组合,用于创建RESTful Web服务。
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping("/hello")
public ResponseEntity<String> hello() {
return ResponseEntity.ok("Hello, Spring MVC!");
}
}
- 视图解析器(View Resolver)
视图解析器用于将控制器返回的视图名称解析为实际的视图对象(如JSP、Thymeleaf模板等)。在Spring MVC中,你可以通过配置InternalResourceViewResolver(对于JSP)或ThymeleafViewResolver(对于Thymeleaf)等bean来指定视图解析器。
然而,在Spring Boot项目中,如果你添加了相应的starter依赖(如spring-boot-starter-thymeleaf),Spring Boot会自动配置视图解析器。
-
消息转换器(Message Converters)
消息转换器用于在HTTP请求和响应中读写数据。Spring MVC提供了多种内置的消息转换器,用于处理JSON、XML等格式的数据。你可以通过配置HttpMessageConverters来自定义消息转换器的行为。 -
静态资源处理
Spring MVC还提供了对静态资源(如CSS、JavaScript、图片等)的支持。你可以通过配置ResourceHandlerRegistry来指定静态资源的映射路径。 -
异常处理
Spring MVC提供了多种异常处理机制,包括使用@ExceptionHandler注解在控制器中处理特定异常,以及使用@ControllerAdvice注解来跨控制器处理异常。
示例:基于Java的Spring MVC配置
虽然Spring Boot使得大多数配置都变得自动化和隐式化,但以下是一个非Spring Boot项目中,通过Java配置Spring MVC的示例框架:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.demo")
public class WebConfig implements WebMvcConfigurer {
// 实现WebMvcConfigurer接口中的方法来自定义Spring MVC的行为
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
// 其他配置...
}
请注意
在Spring Boot项目中,你通常不需要像上面那样显式地配置InternalResourceViewResolver,因为Spring Boot会根据你添加的依赖(如spring-boot-starter-thymeleaf)自动配置视图解析器。
9.3 前后端数据交互
Spring MVC框架控制层框架,主要负责处理前后端之间的数据交互工作,包括从请求中获取入参数据,并向前端返回处理结果。下面就来学习Spring MVC框架是如何交互问题的。
9.3.1 @RequestMapping注解
@RequestMapping 注解是 Spring MVC 中用于将 HTTP 请求映射到特定处理器类或处理器方法的注解。它可以用在类级别或方法级别上。在类级别使用时,它定义了共同的请求路径前缀,该前缀适用于类中的所有方法级映射。在方法级别使用时,它定义了具体的请求路径、请求方法(如 GET、POST)、请求参数等。
RequestMethod中比较常用的类型有以下几种。
- GET: 通常用于查询。
- POST: 通常用于保存。
- PUT: 通常用于修改。
- DELETE: 通常用于删除。
以下是一个使用 @RequestMapping 注解的 Java 代码示例,展示了如何在 Spring MVC 控制器中使用它:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/app") // 类级别的RequestMapping,为类中的所有方法提供一个共同的路径前缀
public class MyController {
// 方法级别的RequestMapping,指定了具体的请求路径"/hello"
@RequestMapping(value = "/hello", method = RequestMethod.GET) // 注意:在Spring 4.3及以后,可以使用@GetMapping作为@RequestMapping(method = RequestMethod.GET)的快捷方式
public ModelAndView hello() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("hello"); // 设置视图名称,Spring MVC会查找对应的视图文件
modelAndView.addObject("message", "Hello, Spring MVC!"); // 向模型中添加属性,可以在视图中访问
return modelAndView;
}
// 使用@GetMapping作为@RequestMapping(method = RequestMethod.GET)的快捷方式
@GetMapping("/greet")
public String greet(@RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {
// 直接返回视图名称,Spring MVC会将其解析为对应的视图文件
// 使用Model对象向视图传递数据
model.addAttribute("name", name);
return "greet"; // 返回视图名称
}
// 注意:在Spring 5.0及更高版本中,RequestMethod类已被标记为过时,但@RequestMapping注解仍然可以使用它来指定请求方法
// 推荐使用@GetMapping、@PostMapping等注解来替代
}
请注意
在上面的示例中,我展示了两种向视图传递数据的方式:一种是通过 ModelAndView 对象,另一种是通过 Model 对象。ModelAndView 对象同时封装了视图名称和模型数据,而 Model 对象仅用于封装模型数据,当方法返回视图名称字符串时,Spring MVC 会自动使用它。
另外,我还展示了 @GetMapping 注解的使用,它是 @RequestMapping(method = RequestMethod.GET) 的快捷方式,用于处理 HTTP GET 请求。Spring 4.3 引入了这些快捷方式注解(如 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 等),以简化常见的 HTTP 方法映射。
9.3.2 入参处理
@RequestParam注解提供了一些参数,比较常见的如下。
- name:参数名,同value。
- value:参数名:同value。
- required:是否必需,默认为true,表示请求中必须包含对应的参数名。若不存在,将抛出异常。
- defaultValue:为参数赋默认值,如分页功能中的页码参数可以赋默认值为1.当前端未传值时,从第一页开始查询。
在Java中,处理HTTP请求的入参(Input Parameters)通常发生在Spring MVC或Spring Boot的控制器(Controller)层。这些入参可以来自URL的查询字符串(Query String)、表单数据(Form Data)、路径变量(Path Variables)、请求体(Request Body)等。以下是一些处理不同来源入参的Java代码示例。
- 路径变量(Path Variables)
路径变量是URL路径的一部分,用于动态地指定资源。在Spring MVC中,你可以使用@PathVariable注解来访问它们。
@GetMapping("/user/{id}")
public ResponseEntity<String> getUserById(@PathVariable("id") Long userId) {
// 使用userId进行逻辑处理
return ResponseEntity.ok("User ID: " + userId);
}
- 查询字符串(Query String)
查询字符串是URL中?后面的部分,用于传递额外的信息。在Spring MVC中,你可以通过方法参数直接访问它们,Spring会自动将查询参数绑定到对应的参数上。
@GetMapping("/search")
public ResponseEntity<String> search(@RequestParam(name = "query", required = false, defaultValue = "defaultQuery") String query) {
// 使用query进行搜索操作
return ResponseEntity.ok("Searching for: " + query);
}
- 表单数据(Form Data)
当表单通过POST请求提交时,表单数据可以作为请求体的一部分发送。在Spring MVC中,你可以使用@ModelAttribute或@RequestParam(对于单个字段)来接收这些数据。
对于复杂对象,使用@ModelAttribute:
@PostMapping("/user")
public ResponseEntity<String> createUser(@ModelAttribute User user) {
// user对象包含了表单中的所有数据
// 进行逻辑处理
return ResponseEntity.ok("User created: " + user.getName());
}
// User类定义
public class User {
private String name;
private String email;
// getters and setters
}
对于简单字段,使用@RequestParam(但通常用于GET请求中的查询参数):
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) {
// 验证用户名和密码
return ResponseEntity.ok("Logged in as: " + username);
}
注意:
对于POST请求中的表单数据,如果数据是JSON格式的,你应该使用@RequestBody来接收。
- 请求体(Request Body)
当客户端发送JSON或XML等格式的请求体时,你可以使用@RequestBody注解来接收这些数据,并将其自动绑定到Java对象上。
@PostMapping("/user")
public ResponseEntity<String> createUser(@RequestBody User user) {
// user对象包含了请求体中的JSON数据
// 进行逻辑处理
return ResponseEntity.ok("User created from JSON: " + user.getName());
}
确保你的Spring Boot项目中包含了处理JSON的依赖(如spring-boot-starter-web),并且你的请求头中包含了正确的Content-Type(如application/json)。
总结
处理HTTP请求的入参在Spring MVC或Spring Boot中是非常直观的。通过使用适当的注解(如@PathVariable、@RequestParam、@ModelAttribute、@RequestBody),你可以轻松地将请求中的数据绑定到Java对象上,进而进行业务逻辑处理。
9.3.3 出参处理
学习了Spring MVC框架从View到Controller的入参处理功能之后,本节学习从Controller层到View层的出参处理。若要从Controller中获取参数内容,就需要进行模型数据(Model)的处理。对于MVC框架来说模型数据最重要的,因为Controller层最终向View层返回模型数据,而View层将会对返回的模型数据进行渲染并输出。所以将模型数据传递给视图是Spring MVC框架的一项重要工作。
Spring MVC提供了多种方式输出模型数据,比较常见的有以下几种。
- 使用ModelAndView对象。
- 使用Model对象。
- 使用Map对象。
- ModelAndView
在Spring MVC中,ModelAndView是一个用于封装模型数据和视图名称的容器。当你想要将处理结果和视图名称一起返回时,ModelAndView是一个非常有用的类。以下是一个使用ModelAndView的Java代码示例,该示例展示了如何在Spring MVC控制器中创建并返回一个ModelAndView对象。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@GetMapping("/hello")
public ModelAndView hello() {
// 创建一个ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
// 设置视图名称,Spring MVC会根据这个名称查找对应的视图文件
// 假设你有一个名为"hello"的JSP文件在/WEB-INF/views/目录下
modelAndView.setViewName("hello");
// 向模型中添加数据,这些数据可以在视图中通过EL表达式访问
modelAndView.addObject("message", "Hello, Spring MVC!");
// 返回ModelAndView对象
return modelAndView;
}
// 另一个示例,展示如何传递一个复杂的对象到视图
@GetMapping("/user")
public ModelAndView showUser() {
ModelAndView modelAndView = new ModelAndView();
// 假设User是一个包含用户信息的类
User user = new User();
user.setName("John Doe");
user.setEmail("john.doe@example.com");
// 设置视图名称
modelAndView.setViewName("user");
// 将用户对象添加到模型中
modelAndView.addObject("user", user);
// 返回ModelAndView对象
return modelAndView;
}
// User类的简单定义
public static class User {
private String name;
private String email;
// getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}
在这个示例中,MyController类包含两个方法,hello和showUser,它们都返回一个ModelAndView对象。hello方法设置了一个简单的消息字符串到模型中,并指定了视图名称为"hello"。showUser方法创建了一个User对象,将其添加到模型中,并指定了视图名称为"user"。
- Model
在Java中,Model 通常不是一个具体的类,而是一个概念,用于表示应用程序中的数据。在MVC(Model-View-Controller)架构中,Model 负责封装与应用程序业务逻辑相关的数据以及操作这些数据的规则。
由于 Model 是一个概念,而不是一个具体的类,因此没有标准的 Model.java 文件。不过,我可以给你一个简单的 Model 类的示例,这个类代表了某种业务实体,比如 User。
package com.example.demo.model;
public class User {
private Long id;
private String name;
private String email;
// 构造方法
public User() {
// 默认构造方法
}
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// Getter 和 Setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// 可能还会有其他业务逻辑方法,比如验证电子邮件地址等
public boolean isValidEmail() {
// 简单的电子邮件验证逻辑
return email != null && email.contains("@");
}
}
在这个例子中,User 类代表了一个用户实体,它包含了用户的ID、姓名和电子邮件地址。这个类提供了基本的getter和setter方法来访问和修改这些属性,以及一个 isValidEmail 方法来验证电子邮件地址的格式是否正确。
在MVC架构中,User 类的实例可以在Controller中被创建和修改,然后传递给View来展示,或者在Service层中被用来执行业务逻辑操作,比如从数据库中检索用户信息或更新用户数据。同时,User 类本身不包含任何与视图或控制器交互的代码,它只关注于表示业务数据和业务逻辑。
- Map
在Java中,Map 是一个接口,它提供了一种将键(Key)映射到值(Value)的对象,一个键可以最多映射到最多一个值。Map 接口的实现类包括 HashMap、TreeMap、LinkedHashMap 等,它们提供了不同的特性和性能。
以下是一个使用 HashMap 作为 Map 接口实现的简单Java代码示例:
import java.util.HashMap;
import java.util.Map;
public class MapExample {
public static void main(String[] args) {
// 创建一个HashMap实例
Map<String, Integer> map = new HashMap<>();
// 向Map中添加键值对
map.put("Apple", 100);
map.put("Banana", 200);
map.put("Cherry", 150);
// 访问Map中的值
System.out.println("Apple的数量: " + map.get("Apple"));
// 遍历Map
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 使用Java 8的forEach和lambda表达式遍历Map
map.forEach((key, value) -> System.out.println(key + ": " + value));
// 检查Map中是否包含某个键
if (map.containsKey("Banana")) {
System.out.println("找到了Banana!");
}
// 检查Map中是否包含某个值(注意:这可能需要遍历整个Map)
if (map.containsValue(150)) {
System.out.println("Map中包含值为150的项!");
}
// 移除Map中的项
map.remove("Cherry");
System.out.println("移除Cherry后,Map的内容为: " + map);
// Map的大小
System.out.println("Map的大小为: " + map.size());
}
}
在这个例子中,我们首先创建了一个 HashMap 的实例,并使用 put 方法向其中添加了几个键值对。然后,我们使用 get 方法来访问特定键对应的值,并使用增强的for循环和Java 8的 forEach 方法与lambda表达式来遍历Map中的所有键值对。此外,我们还展示了如何使用 containsKey 和 containsValue 方法来检查Map中是否包含特定的键或值,以及如何使用 remove 方法来移除Map中的项。最后,我们打印了Map的大小。
请注意
由于 Map 接口的实现(如 HashMap)不保证映射的顺序,因此遍历Map时元素的顺序可能会改变。如果你需要保持元素的插入顺序,可以使用 LinkedHashMap。如果你需要按照键的自然顺序或创建的 Comparator 进行排序,可以使用 TreeMap。
9.4 视图解析器
Spring MVC框架在完成请求处理工作之后,会返回一个ModelAndView对象,其中包含图逻辑名和数据模型。对于那些返回值是String或其他类型的接口,Spring MVC框架也会在内部将它们装配成一个ModelAndView对象,这需要借助视图解析器(ViewResolver)实现。
在Java Web应用程序中,视图解析器(ViewResolver)是MVC(Model-View-Controller)架构中的一个关键组件,它负责将控制器(Controller)返回的逻辑视图名称解析为具体的视图(View)实现。这通常涉及到查找并加载JSP、Thymeleaf模板、FreeMarker模板等视图文件。
在Spring MVC中,视图解析器是通过配置Bean来定义的。这里我将给出一个使用InternalResourceViewResolver(针对JSP)和ThymeleafViewResolver(针对Thymeleaf模板)的Java配置示例。
使用InternalResourceViewResolver(针对JSP)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
public class ViewResolverConfig {
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/"); // 设置JSP文件的位置前缀
resolver.setSuffix(".jsp"); // 设置JSP文件的后缀
return resolver;
}
}
使用ThymeleafViewResolver(针对Thymeleaf模板)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.thymeleaf.ThymeleafViewResolver;
@Configuration
public class ThymeleafViewResolverConfig {
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine()); // 关联Thymeleaf模板引擎
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Bean
public org.thymeleaf.spring5.SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
@Bean
public org.thymeleaf.templateresolver.ITemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("/WEB-INF/templates/"); // 设置模板文件的位置前缀
templateResolver.setSuffix(".html"); // 设置模板文件的后缀
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
}
请注意
上述Thymeleaf配置示例中使用了SpringResourceTemplateResolver来定位模板文件,并通过SpringTemplateEngine与之关联。这是Spring Boot中常见的配置方式,但如果你使用的是标准的Spring MVC项目,并且没有集成Spring Boot的自动配置,那么可能需要做一些调整来确保配置正确。
另外,请注意,随着Spring Boot的流行,很多配置现在都可以通过application.properties或application.yml文件以及Spring Boot的自动配置来简化,而无需显式编写Java配置类。然而,了解如何手动配置这些组件仍然是有价值的,特别是在需要自定义行为或集成非Spring Boot项目的场景中。