【SpringMVC】SpringMVC进阶,类型转换器源码分析,json转换,视图解析器,以及操作各种域的API

SpringMVC

类型转换器

在Web开发中,尤其是使用Spring MVC时,用户通过表单或API传递的请求参数通常是字符串类型 ,但后端模型可能需要其他类型(如DateIntegerLocalDate等)。此时,类转换器可以将字符串转换为目标类型。

内置类型转换器

Stirng------>Boolean类型转换的转换器
StringTobooleanConverter转换器源码


自定义类型转换器

日期转换器

前端表单提交date类型是2021-05-12这种横杠分隔

内置转换器只能转换2021/05/12这种斜杠风格的

如果我们传递了2021-05-12这种情况下我们就可以选择自定义类型转换

可以将横杠分隔字符串,或者/风格的字符串都转换成LocalDate的转换器

java 复制代码
import org.springframework.core.convert.converter.Converter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class StringToDateConverter implements Converter<String, LocalDate> {
    @Override
    public LocalDate convert(String source) {
        if (source == null || source.isEmpty()) {
            return null;
        }
        try {
            // 尝试解析 yyyy-MM-dd 格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            //定义一种规则用来解析yyyy-MM-dd这种格式的字符串
            LocalDate localDate = LocalDate.parse(source, formatter);
            //传递这个字符串和规则,返回一个LocalDate类型的时间类对象
            return localDate;
        } catch (DateTimeParseException e) {
            // 如果失败,尝试解析 yyyy/MM/dd 格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
            LocalDate localDate = LocalDate.parse(source, formatter);
            return localDate;
        }
    }
}

需要配置spring-mvc.xml

测试网络接口(需要有@RequestParam注解)

java 复制代码
    @RequestMapping("/date")
    public String Date(@RequestParam("birthday") LocalDate birthday){
        System.out.println("Date");
        System.out.println(birthday);
        return "forward:/success.jsp";
    }

这样我们就可以成功接受并转换两种风格的日期字符串了

java控制台打印的依旧是-横杠风格的


注解转换

当我们不需要转换两种风格的时候,只需要转换一种-横杠风格的时候,就不需要自定义类型转换器以及xml

可以直接使用**@DateTimeFormat**注解,传递自定义类型的直接转换为日期

弊端:只能转换-横杠风格的日期字符串了,遇到/斜杠风格的日期字符串会404


数据放到响应体中转化成json

@ResponseBody

1.添加依赖

xml 复制代码
    <!-- jackson,帮助进行json转换-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>

2.配置注解驱动

xml 复制代码
<!--    定义注解驱动-->
    <mvc:annotation-driven>
<!--     消息转换器-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="utf-8"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

定义网络接口

结果


查询所有用户

简化


页面跳转

转发和重定向

return 字符串跳转路径

内部是请求转发


请求转发是服务器 内部的

最终浏览器地址是永远是第一次请求的地址

重定向是浏览器 控制的,是发送了多次请求到最终地址

最终浏览器地址是最后一次请求的地址

取数据用转发,其他全是重定向

forward: 请求转发(默认)

redirect:重定向


视图解析器

WEB-INF里面的文件是受保护的

jsp一般放到里面

根据 Servlet 规范,服务器会阻止对WEB - INF目录下资源的直接 HTTP 访问请求。

当客户端发送请求试图访问WEB - INF中的文件时,服务器会返回一个404错误(即使文件实际上存在),而不是将文件内容返回给客户端。

这时候就需要用到视图解析器去访问里面的文件,属于请求转发

本质就是让跳转路径简单

可以设置跳转路径的前缀和后缀,进行拼接

注入bean视图解析器对象

xml 复制代码
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
        <!--要求拼接的前缀-->
        <property name="prefix" value="/WEB-INF/page/"></property>
        <!--要拼接的后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

实际上访问的是/WEB-INF/page/test.jsp


当我们不需要添加前后缀的时候,只需要用forward或者redirect进行标识,这样就不会进行前后缀拼接了


获取原生对象(了解)

我们之前在web阶段我们经常要使用到request对象,response,session对象等。我们也可以通过SpringMVC获取到这些对象。(不过在MVC中我们很少获取这些对象,因为有更简便的方式,避免了我们使用这些原生对象相对繁琐的API。)

我们只需要在方法上添加对应类型的参数即可,但是注意数据类型不要写错了,SpringMVC会把我们需要的对象传给我们的形参。

java 复制代码
@Controller
public class RequestResponseController {
    @RequestMapping("/getReqAndRes")
    public String getReqAndRes(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println();
        return "test";
    }
}

获取请求头

在方法中定义一个参数,参数前加上**@RequestHeader**注解,知道要获取的请求头名即可获取对应请求头的值。

想要获取 device-type 这个请求头则可以按照如下方式定义方法。

java 复制代码
@Controller
public class RequestResponseController {


    @RequestMapping("/getHeader")
    public String getHeader(@RequestHeader(value = "device-type") String deviceType){
        System.out.println(deviceType);
        return "test";
    }
}

获取Cookie

在方法中定义一个参数,参数前加上**@CookieValue** 注解,知道要获取的cookie名即可获取对应cookie的值。

想要获取 JSESSIONID 的cookie值。则可以按照如下方式定义方法。

java 复制代码
@Controller
public class RequestResponseController {

    @RequestMapping("/getCookie")
    public String getCookie(@CookieValue("JSESSIONID") String sessionId){
        System.out.println(sessionId);
        return "test";
    }
}

JSP开发模式(了解)

如果我们使用JSP进行开发,那我们就需要在域中存数据,然后跳转到对应的JSP页面中,在JSP页面中获取域中的数据然后进行相关处理。

使用如果是类似JSP的开发模式就会涉及到往域中存数据携带数据跳转页面的操作。

所以我们来看下如果用SpringMVC进行相关操作。


往Requet域存数据并跳转

Model

我们可以使用Model来往域中存数据。然后使用之前的方式实现页面跳转。

要求访问 /testRequestScope 这个路径时能往Request域中存name和title数据,然后跳转到 /WEB-INF/page/testScope.jsp 这个页面。在Jsp中获取域中的数据。

java 复制代码
@Controller
public class JspController {
    @RequestMapping("/testRquestScope")
    public String testRquestScope(Model model){
        //往请求域存数据
        model.addAttribute("name","三更");
        model.addAttribute("title","不知名Java教程UP主");
        return "testScope";
    }
}

ModelAndView

我们可以使用ModelAndView来往域中存数据和页面跳转。

要求访问 /testRequestScope2 这个路径时能往域中存name和title数据,然后跳转到 /WEB-INF/page/testScope.jsp 这个页面。在Jsp中获取域中的数据。

java 复制代码
@Controller
public class JspController {
    @RequestMapping("/testRquestScope2")
    public ModelAndView testRquestScope2(ModelAndView modelAndView){
        //往域中添加数据
        modelAndView.addObject("name","三更");
        modelAndView.addObject("title","不知名Java教程UP主");
        //页面跳转
        modelAndView.setViewName("testScope");
        return modelAndView;
    }
}

注意要把modelAndView对象作为方法的返回值返回


从Request域中获取数据

我们可以使用**@RequestAttribute** 把他加在方法参数上,可以让SpringMVC帮我们从Request域中获取相关数据。

java 复制代码
@Controller
public class JspController {
    @RequestMapping("/testGetAttribute")
    public String testGetAttribute(@RequestAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingPattern")
                                               String value,HttpServletRequest request){
        System.out.println(value);
        return "testScope";
    }
}

往Session域存数据并跳转

我们可以使用**@SessionAttributes**注解来进行标识,用里面的属性来标识哪些数据要存入Session域。

要求访问 /testSessionScope 这个路径时能往域中存nametitle 数据,然后跳转到 /WEB-INF/page/testScope.jsp 这个页面。在jsp中获取Session域中的数据。

java 复制代码
@Controller
@SessionAttributes({"name"})//表示name这个数据也要存储一份到session域中
public class JspController {
    @RequestMapping("/testSessionScope")
    public String testSessionScope(Model model){
        model.addAttribute("name","三更");
        model.addAttribute("title","不知名Java教程UP主");
        return "testScope";
    }
}

获取Session域中数据

我们可以使用**@SessionAttribute把他加在方法参数上,可以让SpringMVC帮我们从Session域**中获取相关数据。

java 复制代码
@Controller
@SessionAttributes({"name"})
public class JspController {
    @RequestMapping("/testGetSessionAttr")
    public String testGetSessionAttr(@SessionAttribute("name") String name){
        System.out.println(name);
        return "testScope";
    }
}
相关推荐
极客先躯8 分钟前
高级java每日一道面试题-2025年3月05日-微服务篇[Eureka篇]-Eureka在微服务架构中的角色?
java·微服务·架构·服务注册·健康检查·架构服务发现
无极低码34 分钟前
FLASK和GPU依赖安装
后端·python·flask
星际编程喵1 小时前
Flask实时监控:打造智能多设备在线离线检测平台(升级版)
后端·python·单片机·嵌入式硬件·物联网·flask
北漂老男孩2 小时前
IntelliJ IDEA 调试技巧指南
java·ide·intellij-idea
钢铁男儿2 小时前
Python 生成数据(随机漫步)
开发语言·python·信息可视化
八股文领域大手子2 小时前
Leetcode32 最长有效括号深度解析
java·数据库·redis·sql·mysql
上官美丽2 小时前
Springboot中的@ConditionalOnBean注解:使用指南与最佳实践
java·spring boot·mybatis
正经教主2 小时前
【菜鸟飞】在vsCode中安装python的ollama包出错的问题
开发语言·人工智能·vscode·python·ai·编辑器
Dongliner~3 小时前
【QT:多线程、锁】
开发语言·qt
Another Iso3 小时前
Windows安装Apache Maven 3.9.9
java·maven