第九章 Spring MVC框架(2023版本IDEA)


  本章将介绍一种经典的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框架来实现。

  1. 引入依赖
    首先,确保你的项目中引入了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>
  1. 模型(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;  
    }  
}
  1. 视图(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>
  1. 控制器(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  
    }  
}
  1. 配置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;  
    }  
}
  1. 部署和运行
    将上述代码和配置文件部署到支持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类。

  1. 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>
  1. 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;  
    }  
}
  1. 控制器(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";  
    }  
}
  1. 视图(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代码示例。

  1. Maven依赖
    首先,确保你的pom.xml文件中包含了必要的依赖,与之前的示例类似,但这里不再重复。

  2. 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);  
    }  
}
  1. 控制器
    创建一个控制器类,并使用@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"; // 返回视图的名称  
    }  
}
  1. 视图
    将视图文件(如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集成得更好。

  1. 配置文件(可选)
    如果你的应用程序需要额外的配置(比如数据库连接、服务器设置等),你可以在application.properties或application.yml文件中添加它们。

  2. 运行你的应用程序
    使用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的自动配置特性。

  1. 配置DispatcherServlet
    在Spring MVC中,DispatcherServlet是前端控制器,它接收所有的HTTP请求,并将它们分发给相应的控制器处理。在传统的Spring MVC项目中(非Spring Boot),你需要在web.xml中配置DispatcherServlet,但在基于Java配置的项目中,你可以通过实现WebApplicationInitializer接口来配置它。

然而,由于Spring Boot的流行,这里我们主要关注如何通过Java配置来设置Spring MVC,但请注意,在Spring Boot项目中,你通常不需要直接配置DispatcherServlet,因为Spring Boot会自动为你做这件事。

  1. 配置Spring MVC
    在Spring MVC中,你可以通过实现WebMvcConfigurer接口(或其父接口WebMvcConfigurerAdapter,但在Spring 5.0及更高版本中已被弃用)来定制Spring MVC的行为。然而,在Spring Boot项目中,你通常会通过application.properties或application.yml文件以及添加适当的@Bean来配置。

  2. 控制器(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!");  
    }  
}
  1. 视图解析器(View Resolver)
    视图解析器用于将控制器返回的视图名称解析为实际的视图对象(如JSP、Thymeleaf模板等)。在Spring MVC中,你可以通过配置InternalResourceViewResolver(对于JSP)或ThymeleafViewResolver(对于Thymeleaf)等bean来指定视图解析器。

然而,在Spring Boot项目中,如果你添加了相应的starter依赖(如spring-boot-starter-thymeleaf),Spring Boot会自动配置视图解析器。

  1. 消息转换器(Message Converters)
    消息转换器用于在HTTP请求和响应中读写数据。Spring MVC提供了多种内置的消息转换器,用于处理JSON、XML等格式的数据。你可以通过配置HttpMessageConverters来自定义消息转换器的行为。

  2. 静态资源处理
    Spring MVC还提供了对静态资源(如CSS、JavaScript、图片等)的支持。你可以通过配置ResourceHandlerRegistry来指定静态资源的映射路径。

  3. 异常处理
    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代码示例。

  1. 路径变量(Path Variables)
    路径变量是URL路径的一部分,用于动态地指定资源。在Spring MVC中,你可以使用@PathVariable注解来访问它们。
@GetMapping("/user/{id}")  
public ResponseEntity<String> getUserById(@PathVariable("id") Long userId) {  
    // 使用userId进行逻辑处理  
    return ResponseEntity.ok("User ID: " + userId);  
}
  1. 查询字符串(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);  
}
  1. 表单数据(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来接收。

  1. 请求体(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对象。
  1. 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"。

  1. 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 类本身不包含任何与视图或控制器交互的代码,它只关注于表示业务数据和业务逻辑。

  1. 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项目的场景中。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值