【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";
    }
}
相关推荐
GetcharZp26 分钟前
玩转 Linux 机器视觉:手把手带你搞定 Ubuntu 下海康工业相机 C++ SDK
后端
星星在线4 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒5 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x5 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
NE_STOP6 小时前
Vide Coding--AI编程工具的选择
java
袋鱼不重6 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
用户8356290780516 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还6 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy886 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
LDR0066 小时前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言