三、SpringMVC响应数据
3.1 handler方法分析
理解handler方法的作用和组成:
/**
* TODO: 一个controller的方法是控制层的一个处理器,我们称为handler
* TODO: handler需要使用@RequestMapping/@GetMapping系列,声明路径,在HandlerMapping中注册,供DS查找!
* TODO: handler作用总结:
* 1.接收请求参数(param,json,pathVariable,共享域等)
* 2.调用业务逻辑
* 3.响应前端数据(页面(不讲解模版页面跳转),json,转发和重定向等)
* TODO: handler如何处理呢
* 1.接收参数: handler(形参列表: 主要的作用就是用来接收参数)
* 2.调用业务: { 方法体 可以向后调用业务方法 service.xx() }
* 3.响应数据: return 返回结果,可以快速响应前端数据
*/
@GetMapping
public Object handler(简化请求参数接收){
调用业务方法
返回的结果 (页面跳转,返回数据(json))
return 简化响应前端数据;
}
总结: 请求数据接收,我们都是通过handler的形参列表
前端数据响应,我们都是通过handler的return关键字快速处理!
springmvc简化了参数接收和响应!
3.2 页面跳转控制
3.2.1 快速返回模板视图
-
开发模式回顾
在 Web 开发中,有两种主要的开发模式:前后端分离和混合开发。
前后端分离模式:[重点]
指将前端的界面和后端的业务逻辑通过接口分离开发的一种方式。开发人员使用不同的技术栈和框架,前端开发人员主要负责页面的呈现和用户交互,后端开发人员主要负责业务逻辑和数据存储。前后端通信通过 API 接口完成,数据格式一般使用 JSON 或 XML。前后端分离模式可以提高开发效率,同时也有助于代码重用和维护。
混合开发模式:
指将前端和后端的代码集成在同一个项目中,共享相同的技术栈和框架。这种模式在小型项目中比较常见,可以减少学习成本和部署难度。但是,在大型项目中,这种模式会导致代码耦合性很高,维护和升级难度较大。
对于混合开发,我们就需要使用动态页面技术,动态展示Java的共享域数据!!
-
jsp技术了解
JSP(JavaServer Pages)是一种动态网页开发技术,它是由 Sun 公司提出的一种基于 Java 技术的 Web 页面制作技术,可以在 HTML 文件中嵌入 Java 代码,使得生成动态内容的编写更加简单。
JSP 最主要的作用是生成动态页面。它允许将 Java 代码嵌入到 HTML 页面中,以便使用 Java 进行数据库查询、处理表单数据和生成 HTML 等动态内容。另外,JSP 还可以与 Servlet 结合使用,实现更加复杂的 Web 应用程序开发。
JSP 的主要特点包括:
- 简单:JSP 通过将 Java 代码嵌入到 HTML 页面中,使得生成动态内容的编写更加简单。
- 高效:JSP 首次运行时会被转换为 Servlet,然后编译为字节码,从而可以启用 Just-in-Time(JIT)编译器,实现更高效的运行。
- 多样化:JSP 支持多种标准标签库,包括 JSTL(JavaServer Pages 标准标签库)、EL(表达式语言)等,可以帮助开发人员更加方便的处理常见的 Web 开发需求。
总之,JSP 是一种简单高效、多样化的动态网页开发技术,它可以方便地生成动态页面和与 Servlet 结合使用,是 Java Web 开发中常用的技术之一。
-
准备jsp页面和依赖
pom.xml依赖
<!-- jsp需要依赖! jstl--> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>3.0.0</version> </dependency>
jsp页面创建
建议位置:/WEB-INF/下,避免外部直接访问!
位置:/WEB-INF/views/home.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <!-- 可以获取共享域的数据,动态展示! jsp== 后台vue --> ${msg} </body> </html>
-
快速响应模版页面
-
配置jsp视图解析器
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器 @Configuration @ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描 //WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现 public class SpringMvcConfig implements WebMvcConfigurer { //配置jsp对应的视图解析器 @Override public void configureViewResolvers(ViewResolverRegistry registry) { //快速配置jsp模板语言对应的 registry.jsp("/WEB-INF/views/",".jsp"); } }
-
handler返回视图
/** * 跳转到提交文件页面 /save/jump * * 如果要返回jsp页面! * 1.方法返回值改成字符串类型 * 2.返回逻辑视图名即可 * <property name="prefix" value="/WEB-INF/views/"/> * + 逻辑视图名 + * <property name="suffix" value=".jsp"/> */ @GetMapping("jump") public String jumpJsp(Model model){ System.out.println("FileController.jumpJsp"); model.addAttribute("msg","request data!!"); return "home"; }
-
3.2.2 转发和重定向
在 Spring MVC 中,Handler 方法返回值来实现快速转发,可以使用 redirect
或者 forward
关键字来实现重定向。
@RequestMapping("/redirect-demo")
public String redirectDemo() {
// 重定向到 /demo 路径
return "redirect:/demo";
}
@RequestMapping("/forward-demo")
public String forwardDemo() {
// 转发到 /demo 路径
return "forward:/demo";
}
//注意: 转发和重定向到项目下资源路径都是相同,都不需要添加项目根路径!填写项目下路径即可!
总结:
- 将方法的返回值,设置String类型
- 转发使用forward关键字,重定向使用redirect关键字
- 关键字: /路径
- 注意:如果是项目下的资源,转发和重定向都一样都是项目下路径!都不需要添加项目根路径!
3.3 返回JSON数据(重点)
3.3.1 前置准备
导入jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
添加json数据转化器
@EnableWebMvc
//TODO: SpringMVC对应组件的配置类 [声明SpringMVC需要的组件信息]
//TODO: 导入handlerMapping和handlerAdapter的三种方式
//1.自动导入handlerMapping和handlerAdapter [推荐]
//2.可以不添加,springmvc会检查是否配置handlerMapping和handlerAdapter,没有配置默认加载
//3.使用@Bean方式配置handlerMapper和handlerAdapter
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {
}
3.3.2 @ResponseBody
-
方法上使用@ResponseBody
可以在方法上使用
@ResponseBody
注解,用于将方法返回的对象序列化为 JSON 或 XML 格式的数据,并发送给客户端。在前后端分离的项目中使用!测试方法:
@GetMapping("/accounts/{id}") @ResponseBody public Object handle() { // ... return obj; }
具体来说,
@ResponseBody
注解可以用来标识方法或者方法返回值,表示方法的返回值是要直接返回给客户端的数据,而不是由视图解析器来解析并渲染生成响应体(viewResolver没用)。测试方法:
@RequestMapping(value = "/user/detail", method = RequestMethod.POST) @ResponseBody public User getUser(@RequestBody User userParam) { System.out.println("userParam = " + userParam); User user = new User(); user.setAge(18); user.setName("John"); //返回的对象,会使用jackson的序列化工具,转成json返回给前端! return user; }
返回结果:
-
类上使用@ResponseBody
如果类中每个方法上都标记了 @ResponseBody 注解,那么这些注解就可以提取到类上。
@ResponseBody //responseBody可以添加到类上,代表默认类中的所有方法都生效! @Controller @RequestMapping("param") public class ParamController {
3.3.3 @RestController
类上的 @ResponseBody 注解可以和 @Controller 注解合并为 @RestController 注解。所以使用了 @RestController 注解就相当于给类中的每个方法都加了 @ResponseBody 注解。
RestController源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
3.4 返回静态资源处理
-
静态资源概念
资源本身已经是可以直接拿到浏览器上使用的程度了,不需要在服务器端做任何运算、处理。典型的静态资源包括:
- 纯HTML文件
- 图片
- CSS文件
- JavaScript文件
- ……
-
静态资源访问和问题解决
-
web应用加入静态资源
-
手动构建确保编译
-
访问静态资源
-
问题分析
- DispatcherServlet 的 url-pattern 配置的是“/”
- url-pattern 配置“/”表示整个 Web 应用范围内所有请求都由 SpringMVC 来处理
- 对 SpringMVC 来说,必须有对应的 @RequestMapping 才能找到处理请求的方法
- 现在 images/mi.jpg 请求没有对应的 @RequestMapping 所以返回 404
-
问题解决
在 SpringMVC 配置配置类:
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器 @Configuration @ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描 //WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现 public class SpringMvcConfig implements WebMvcConfigurer { //配置jsp对应的视图解析器 @Override public void configureViewResolvers(ViewResolverRegistry registry) { //快速配置jsp模板语言对应的 registry.jsp("/WEB-INF/views/",".jsp"); } //开启静态资源处理 <mvc:default-servlet-handler/> @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
再次测试访问图片:
-
新的问题:其他原本正常的handler请求访问不了了
handler无法访问
解决方案:
@EnableWebMvc //json数据处理,必须使用此注解,因为他会加入json处理器
-
回顾总结
第二章复习
接收参数
1.路径设置
@RequestMapping(value="地址",method="请求方式") 类 | 方法
@GetMapping / @PostMapping 方法
2.接收参数【重点】
param
直接接收 handler(类型 形参名) 形参名 = 请求参数名
注解指定 handler(@RequestParam(name="请求参数名",required=true,defaultValue="默认值"))
一名多值 handler(@RequestParam List key)
实体接收 handler(实体 对象) 对象的属性名 = 请求参数名
路径参数
设置动态路径和标识 /{key}/info/{key}
接收路径 handler(@PathVariable(动态路径key) 类型 形参名)
json
数据接收 handler(@RequestBody 实体类 对象)
准备工作:
1.导入jackson依赖
2.@EnableWebMvc [加入handlerMapping 加入handlerAdapter 给handlerAdapter配置json处理器]
3.cookie接收
handler(@CookieValue("cookie的名字"))
4.请求头接收
handler(@RequestHeader("cookie的名字"))
5.原生api获取
handler(httpServletRequest,response,session)
ServletContext -> ioc -> 全局变量 @Autowired
6.共享域获取
原生api方式即可
前后端分离与不分离的区别
新建模块,导入依赖
<!-- jsp需要依赖! jstl-->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
为了保护不让外部直接访问到界面,通常要把页面放在webapp 下的web-inf 包下
<%--
Created by IntelliJ IDEA.
User: Jackiechan
Date: 2023/7/31
Time: 12:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- request.setAttribute("data","hello jsp!!");
vue {{key}}
-->
<font color='red'>${data}</font>
</body>
</html>
然后便携配置类
config包下的MvcConfig 类 去实现快速添加相应的前后缀功能
package com.atguigu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* projectName: com.atguigu.config
*
* @author: 赵伟风
* description: mvc组件的配置类
*/
@Configuration
@ComponentScan("com.atguigu.jsp")
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
//handlerMapping handlerAdapter json转化器 当然直接注解 @EnableWebMvc即可
//试图解析器,指定前后锥
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
//registry可以快速添加前后缀
registry.jsp("/WEB-INF/views/",".jsp");
//handler -> index
}
//开启静态资源查找
// dispatcherServlet -> handlerMapping找有没有对应的handler -》【 没有 -》 找有没有静态资源 】
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
然后初始化,SpringMVCInit类
package com.atguigu.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* projectName: com.atguigu.config
*
* @author: 赵伟风
* description:
*/
public class SpringMVCInit extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Specify {@code @Configuration} and/or {@code @Component} classes for the
* {@linkplain #createRootApplicationContext() root application context}.
*
* @return the configuration for the root application context, or {@code null}
* if creation and registration of a root context is not desired
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
/**
* Specify {@code @Configuration} and/or {@code @Component} classes for the
* {@linkplain #createServletApplicationContext() Servlet application context}.
*
* @return the configuration for the Servlet application context, or
* {@code null} if all configuration is specified through root config classes.
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MvcConfig.class};
}
/**
* Specify the servlet mapping(s) for the {@code DispatcherServlet} —
* for example {@code "/"}, {@code "/app"}, etc.
*
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
然后创建jsp包下的JspController类 实现 index方法以及转发重定向
package com.atguigu.jsp;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* projectName: com.atguigu.jsp
*
* @author: 赵伟风
* description: 快速返回一个jsp页面
*/
@Controller
@RequestMapping("jsp")
public class JspController {
/**
* TODO:快速查找试图
* 1. 方法的返回值是字符串类型
* 2. 不能添加@ResponseBody,直接返回给字符串给浏览器,不找视图,不走试图解析器
* 3. 返回值 对应中间的视图名称即可 /springmvc/jsp/index
*/
@GetMapping("index")
public String index(HttpServletRequest request){
request.setAttribute("data","hello jsp!!!");
System.out.println("JspController.index");
return "index";
}
/**
* 转发:只能是项目下的资源
* 1.方法的返回值写成字符串
* 2.不能添加responseBody注解
* 3.返回的字符串前 forward: /转发地址
*/
//转发
@GetMapping("forward")
public String forward(){
System.out.println("JspController.forward");
return "forward:/jsp/index";
}
/**
* 重定向:
* 1.方法返回值写成字符串类型
* 2.不能添加responseBody注解
* 3.返回字符串前面 redirect: /重定向的地址
*/
/**
*
* 路径细节:【不使用springmvc request response】
* 转发是项目下的资源跳转。路径: 项目下的地址 /jsp/index 忽略 applicationContext
* 重定向项目下的资源可以是项目外的地址 重定向属于二次请求 路径: 项目下的地址 全地址 /springmvc/jsp/index 不忽略 applicationContext
* 使用springmvc路径语法:
* "forward: 路径 | redirect: 路径 " 重定向,资源的地址也不需要写项目的根路径! /jsp/index
* 转发和重定向的地址都一样了!如果你加了则会重复 /springmvc/jsp/index - > /springmvc/springmvc/jsp/index
*/
//重定向
@GetMapping("redirect")
public String redirect(){
System.out.println("JspController.redirect");
return "redirect:/jsp/index";
}
@GetMapping("redirect/baidu")
public String redirectBaidu(){
System.out.println("JspController.redirectBaidu");
return "redirect:http://www.baidu.com";
}
}
//json数据
还是和上述差不多
导入依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
编写实体类pojo下的User类
package com.atguigu.pojo;
import lombok.Data;
/**
* projectName: com.atguigu.pojo
*
* @author: 赵伟风
* description:
*/
@Data
public class User {
private String name;
private int age;
}
编写配置类config 更改包得扫描
然后编写json包下的JsonController
package com.atguigu.json;
import com.atguigu.pojo.User;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* projectName: com.atguigu.json
*
* @author: 赵伟风
* description:
*/
//@Controller
@RequestMapping("json")
//@ResponseBody //返回json的注解。添加到类和方法上!
@RestController // @Controller + @ResponseBody
public class JsonController {
/**
*
* TODO: @ResponseBody 数据直接放入响应体返回! 也不会在走视图解析器
* 快速查找视图, 转发和重定向都不生效了!
*/
@GetMapping("data")
public User data(){
// 对象 -》json -> {}
// 集合 -》json -> []
User user = new User();
user.setName("two dogs!");
user.setAge(3);
return user; // user-> handlerAdapter -> json -》 @ResponseBody -> json直接返回 【前后端分离模式】
}
@GetMapping("data2")
public List<User> data1(){
User user = new User();
user.setName("two dogs!");
user.setAge(3);
List<User> users = new ArrayList<>();
users.add(user);
return users;
}
}
//访问静态资源
要放在resource下不用放在web-inf下,也就是说不用保护,外部可以直接访问到
但如果没有开启的话那就就会访问不到,因为外部访问只去handlerMapping中去找,而并未找静态资源
所以要在MVCConfig类中去开启这个功能
//开启静态资源查找
// dispatcherServlet -> handlerMapping找有没有对应的handler -》【 没有 -》 找有没有静态资源 】
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
(“data2”)
public List data1(){
User user = new User();
user.setName(“two dogs!”);
user.setAge(3);
List<User> users = new ArrayList<>();
users.add(user);
return users;
}
}
//访问静态资源
要放在resource下不用放在web-inf下,也就是说不用保护,外部可以直接访问到
但如果没有开启的话那就就会访问不到,因为外部访问只去handlerMapping中去找,而并未找静态资源
[外链图片转存中...(img-ec1Pce2T-1719065296251)]
所以要在MVCConfig类中去开启这个功能
//开启静态资源查找
// dispatcherServlet -> handlerMapping找有没有对应的handler -》【 没有 -》 找有没有静态资源 】
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
[外链图片转存中...(img-gvBtTByr-1719065296252)]
##
标签:实战,return,SpringMVC,表述,json,handler,jsp,import,public
From: https://blog.csdn.net/weixin_65644655/article/details/139889007