SpringMVC---确定目标方法POJO类型参数

SpringMVC确定目标方法POJO类型入参的过程

  1. 确定一个key:
  • 若目标方法的POJO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母小写
  • 若使用了@ModelAttribute来修饰,则key为@ModelAttribute注解的value属性值
  1. 在implicitModel中查找key对应的对象,若存在,则作为参数传入
  • 若在@ModeAttribute标记的方法中的Map中保存过,则key和1确定的key一直,则会获取到.
  • 若implicitModel中不存在key中对应的对象,则检查当前的Handler是否使用@SessionAttributes注解修饰,若是用了该注解,且@SessionAttributes注解的value属性值包含了key,则会从HttpSession中获取key所对应的value值,若存在则直接传到目标方法的入参中,若不存在则抛出异常,
  • 若Handler没有表示@SessionAttributes注解或@SessionAttributes注解的value之中不包含key,则回通过反射来创建POJO类型的参数,传入为目标方法的参数
  • SpringMVC会把key和POJO类型的对象保存到implictiModel中,进而会保存到request中

@ModelAttribute注解修饰POJO类型的入参

  • @ModelAttribute注解也可以来修饰目标方法POJO类型的入参,器value属性值有如下的作用
  1. SpringMVC会使用value属性值在implicitModek中查找对应的对象,若存在则会直接传入到目标方法的入参中,
  2. SpringMVC会以value为key,POJO类型的睢县为value,存入道request中
  • 示例:使用@ModelAttribute注解修饰入参
    @ModelAttribute//SpringMVC在执行映射请求方法之前,会先调用带有@ModelAttribute 注解的方法
    public void getUser(@RequestParam(value = "uid",required = false) Integer uid,Map<String,Object> map){

        //模拟从数据库中获取用户数据
        User user =new User();
        user.setUid(uid);
        user.setUname("xiemaoshu");
        user.setPassword("12345");
        map.put("xiemaoshu",user);//将user数据保存到request请求域之中

        System.out.println("获取uid = "+uid+" 的用户数据"+user);
    }

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("xiemaoshu") User user){
        System.out.println("执行修改操作:"+user);
        return SUCCESS;
    }

@SessionAttributes注解引发的异常

  • 当使用@SessionAttributes注解修饰类的时候,如果目标方法的POJO类型参数没有在implicitModel中被找到,则回到HttpSession中查找,如果没有找到,则会抛出一个异常,

  • 异常产生:

@SessionAttributes(types = {User.class,String.class},value = {"xiemaoshu"})
@Controller
public class HelloWorld {
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("xiemaoshu") User user){
        System.out.println("执行修改操作:"+user);
        return SUCCESS;
    }
}
  • 此时@SessionAttributes注解中的value值中有"xiemaoshu",于目标方法中的@ModelAttribute注解中的"xiemaoshu"一致.
  • 因此此时执行目标方法时会先在HttpSession中寻找key为"xiemaoshu"的属性,如果没有找到,就会抛出异常

在这里插入图片描述

  • 解决的方法有两种:

    1. 将入参的参数名于@SessionAttributes注解的value值不一致
    2. 添加@ModelAttribute注解修饰的方法,在方法中使用Map集合添加key为"xiemaoshu"的属性
  • 修改参数名称

@SessionAttributes(types = {String.class},value = {"xiemaoshu"})
@Controller
public class HelloWorld {
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("执行修改操作:"+user);
        return SUCCESS;
    }
  • 添加@ModelAttribute注解的方法
@SessionAttributes(types = {User.class,String.class},value = {"xiemaoshu"})
@Controller
public class HelloWorld {

    @ModelAttribute//SpringMVC在执行映射请求方法之前,会先调用带有@ModelAttribute 注解的方法
    public void getUser(@RequestParam(value = "uid",required = false) Integer uid,Map<String,Object> map){

        //模拟从数据库中获取用户数据
        User user =new User();
        user.setUid(uid);
        user.setUname("xiemaoshu");
        user.setPassword("12345");
        map.put("xiemaoshu",user);//将user数据保存到request请求域之中

        System.out.println("获取uid = "+uid+" 的用户数据"+user);
    }

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("xiemaoshu") User user){
        System.out.println("执行修改操作:"+user);
        return SUCCESS;
    }
}

视图解析流程分析

  • 目标方法返回的类型无论是String类型还是ModelAndView最终SpringMVC都会解析为一个ModelAndView类型
  • 随后再通过试图解析器解析出将逻辑视图解析为一个真实的物理视图

在这里插入图片描述

  • 示例代码
    @RequestMapping("/testView")
    public String testView(String uid){
        System.out.println(uid);
        return SUCCESS;
    }
  • 在返回时打上断点

在这里插入图片描述

  1. 在DispatcherServlet类中会执行448行代码,得到一个mv对象,这个mv对象就是ModelAndView对象

在这里插入图片描述

在这里插入图片描述

  • 此时ModelAndView中的属性为,此时的view属性还只是一个逻辑视图,字符串=“success”

在这里插入图片描述

  1. 接着在DispatcherServlet类中的461行中打上断点,此时会执行processDispatchResult()方法

在这里插入图片描述

  1. processDispatchResult()方法处理方法的返回结果,判断目标方法是否有异常,如果有异常就会将方法的返回页面定义为异常页面.
  • 如果没有异常,则会执行一个重要的发那个方法reader()
    在这里插入图片描述

  • reader()方法

    • reader()发那个发中使用一个"View"类描述视图,执行了一个resolveViewName()方法,处理视图
      在这里插入图片描述
  • resolveViewName()方法
    在这里插入图片描述

  • 执行完resolveViewName()方法之后,view属性中的url已经变为"/WEB-INF/pages/success.jsp"路径

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

JstlView

在这里插入图片描述

  • 要导入的jar包

在这里插入图片描述

  • 示例:编写三个国际化资源文件

    1. i18n.properties
    2. i18n_zh_CN.properties
    3. i18n_en_US.properties
  • i18n.properties

i18n.username=Username
i18n.password=Password
  • i18n_zh_CN.properties
i18n.username=用户名
i18n.password=密码
  • i18n_en_US.properties
i18n.username=Username
i18n.password=Password
  • 配置国际化资源文件

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
  <property name="basename" value="i18n"/>
</bean>
  • 定义显示页面
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<fmt:message key="i18n.username" />
<br>
<fmt:message key="i18n.password" />

view-controller标签

  • 如果希望直接访问一个路径,而不通过Handler方法转发到目标路径,就可以子SpringMVC配置文件中配置<view-controller\ > 标签来配置

  • 例如:想要直接访问一个"WEB-INFO/pages/i18n_show.jsp"文件,则可以在SpringMVC配置文件中这样配置

<mvc:view-controller path="/i18nShow" view-name="i18n_show"/>
    @RequestMapping("/testJstl")
    public String testJstl(String uid){
        System.out.println(uid);
        return "i18n_show";
    }

在这里插入图片描述

  • 如果希望注解中的路径也能够生效,那么需要在SpringMVC中配置如下标签
<mvc:annotation-driven></mvc:annotation-driven>

自定义视图

  • 当SpringMVC提供的视图无法满足我们的需求的时候,就可以自定义自己所需要的视图,要想自定义视图,需要实现SpringMVC提供的一个接口"View"
  • 实现View接口中的getContentType()和render()方法即可
  • 在getContentType()方法中返回视图的MIME文件类型
  • 在render()方法中定义视图的渲染操作.
package mao.shu.springmvc.view;

import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Component
public class HelloView implements View {
    @Override
    public String getContentType() {
        return "text/html";
    }

    @Override
    public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        httpServletResponse.getWriter().print("HelloWorld " + new java.util.Date());
    }
}

  • 要想使用自定义的视图,则需要在SpringMVC的配置文件中,添加一个视图解析器:“BeanNameViewResolver”
    <!--配置视图解析器
        这个试图解析器根据Bean名称来选择使用的解析器
        order 属性设置试图解析器的优先级,默认值为Integer的最大值,数值越小 优先级越高
    -->
    <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="100"/>
    </bean>
  • BeanNameViewResolver 类中视图解析流程,主要是用通过Bean的名称在IOC容器中得到自定义的View类的实例化对象,所以自定义的View类也应该配置IOC容器自动注入
    在这里插入图片描述

  • 测试:定义一个请求映射方法

@RequestMapping("/testCusto")
public String testCusto(String uid){
    System.out.println(uid);
    return "helloView";
}

在这里插入图片描述

在这里插入图片描述

重定向

在这里插入图片描述

  • 示例:
 @RequestMapping("/testRedirect")
 public String testRedirect(){
     return "redirect:/index.jsp";//跳转到/index.jsp页面中
 }
  • 在调试运行时会发现在创建视图的时候,会执行以下的代码,当字符串以"redirect"开头时,创建的是一个RedirectView类型的视图
  • 当字符串以"forward"开头时创建的时InternalResourceView类型的视图

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值