1、使用默认内置视图解析器(ViewResolver)

  1. <!-- 默认视图解析器, 配置前缀和后缀 简化我们的开发-->
  2. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" name="viewResolver">
  3. <property name="prefix" value="/WEB-INF/views/" />
  4. <property name="suffix" value=".jsp" />
  5. </bean>

2、使用视图控制器

如果我们有些请求只是想跳转页面,不需要来后台处理什么逻辑,我们无法在Action中写一个空方法来跳转,直接在中配置一个如下的视图跳转控制器即可(不经过Action,直接跳转页面)

 <!--视图控制器 立即访问 path:需要映射的路径 view-name:对应的文件名称-->
    <mvc:view-controller path="/" view-name="index" />
    <mvc:view-controller path="main" view-name="main" />

3、使用Model,Map,ModelMap传输数据到页面

    在刚开始的helloworld项目中,我们传递了参数回到我们页面,但是后续的操作都只是接受用户的请求,那么在SpringMVC中除了可以使用原生servlet的对象传递数据之外,还有什么其他的方式呢?
package com.xixi.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Controller
public class DTVController {



    /**
     * 使用Servlet API的方式传输数据到页面
     **/
    @RequestMapping("/servletAPI")
    public String servletAPI(HttpServletRequest request){
        request.setAttribute("type","servletAPI");
        return "main";
    }

    //     * 使用model的方式传输数据到页面
    @RequestMapping("/model")
    public String model(Model model){
        System.out.println(model.getClass());
        model.addAttribute("type","model");
        return "main";
    }

    //     * 使用modelMap的方式传输数据到页面
    @RequestMapping("/modelMap")
    public String model(ModelMap model){
        System.out.println(model.getClass());
        model.addAttribute("type","modelMap");
        return "main";
    }


    //     * 使用modelMap的方式传输数据到页面
    @RequestMapping("/map")
    public String model(Map map){
        System.out.println(map.getClass());
        map.put("type","map");
        return "main";
    }


}

image.png
model modelMap map 其实底层都是BindingAwareModelMap实现的
image.png

4.使用ModelAndView对象传输数据到页面


    @RequestMapping("/modelAndView")
    public ModelAndView modelAndView(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("main");
        modelAndView.addObject("type","modelAndView");
        return modelAndView;


    }

5.使用session传输数据到页面

怎么往session设置属性?
1.通过servlet api的方式去读写session
1. 通过参数绑定的方式去获取servlet api
2.通过自动注入的方式去获取servlet api(推荐使用这种方式)

@Autowired
private HttpSession session;
/**
 * 通过自动注入的方式去获取servlet api
 */
@RequestMapping("/autowired/session")
public String session02(){
    session.setAttribute("type","autowired-session");
    return "main";
}

通过springmvc提供的注解方式去读写session
1. @SessionAttributes
用在类上面的,写入session的。

// 从model中获取指定的属性写入session中
// 底层会从model中去找一个叫做type的属性
// 找到了会将type设置一份到session中
// 这种方式是依赖model的
// 当前控制器下所有的处理方法 都会将model指定的属性写入session
  1. @SessionAttribute
    用在参数上面的,读取session的。 ```
  • required 用来设置session中某个属性必须存在 , 不存在则会报错:HTTP Status 400 - Missing session attribute ‘type’ of type String
  • model和session是互通的:session可以通过model中去获取写入指定的属性, model也会从session中自动写入指定的属性 ```
  1. @SessionAttributes
    用在类上面的,负责写入session
    @Controller
@Controller
// 通过model中指定的属性去写入到session,同时也会从session中写入指定的属性到model,
// 所以使用SessionAttributes的情况下 model和session是共同的
// 使用该方式设置session是依赖model
@SessionAttributes("type")
public class DTVController {
  1. @SessionAttribute
    用在参数上面的,负责读取session
    默认指定的属性是必须要存在的,如果不存在则会报错,可以设置required =false 不需要必须存在,不存在默认绑定null

@RequestMapping("/getSession")
public String getSession(@SessionAttribute(value="type",required = false) String type){
    System.out.println(type);
    return "main";
}

6、使用@ModelAttribute来获取请求中的数据常用的使用场景

常用的使用场景
1.写在方法上面
@ModelAttribute的方法会在当前处理器中所有的处理方法之前调用
1.通过@ModelAttribute来给全局变量赋值(不推荐)
2. 当我们调用执行全字段的更新数据库操作时,假如提供给用户的修改字段只有部分几个,这个时候就会造成其他字段更新丢失:
解决:
1.自己定制update语句, 只更新指定的那些字段
2.如果无法定制sql语句, 可以在更新之前进行查询, 怎么在更新之前查询?只能在springmvc 绑定请求参数之前查询, 利用@ModelAttribute就可以在参数绑定之前查询, 但是怎么将查询出来的对象和参数的对象进行合并? springmvc具有该特性, 会将model中和参数名相同的属性拿出来进行合并,将参数中的新自动进行覆盖,没有的字段进行保留。这样就可以解决这个问题。
2.写在参数上面
可以省略,加上则会从model中获取一个指定的属性和参数进行合并,因为model和sessionAttribute具有共通的特性,所以如果session中有对应的属性也会进行合并.

@ModelAttribute("user")

@ModelAttribute注解用于将方法的参数或者方法的返回值绑定到指定的模型属性上,并返回给web视图。首先来介绍一个业务场景,来帮助大家做理解,在实际工作中,有些时候我们在修改数据的时候可能只需要修改其中几个字段,而不是全部的属性字段都获取,那么当提交属性的时候,从form表单中获取的数据就有可能只包含了部分属性,此时再向数据库更新的时候,肯定会丢失属性,因为对象的封装是springmvc自动帮我们new的,所以此时需要先将从数据库获取的对象保存下来,当提交的时候不是new新的对象,而是在原来的对象上进行属性覆盖,此时就需要使用@ModelAttribute注解。

总结:通过刚刚的给参数赋值,大家应该能够发现,当给方法中的参数设置值的时候,如果添加了@ModelAttribute注解,那么在查找值的时候,是遵循以下方式:
1、方法的参数使用参数的类型首字母小写,或者使用@ModelAttribute(“”)的值
2、先看之前是否在model中设置过该属性值,如果设置过就直接获取
3、看@SessionAttributes注解标注类中的方法是否给session中赋值,如果有的话,也是直接获取,没有报异常
3种方式的获取servlet—api的线程安全问题:
线程不安全=并发问题: 同一个时间,多个线程,同时对共享数据/变量/资源 进行读写操作,就会产生并发问题(脏读、幻影读…)
1.通过参数绑定的方式
是线程安全的,因为参数绑定的方式变量是方法级别的,所以每次请求方法都会在内存中开辟自己独立的空间。
2.通过@AutoWired自动注入的方式
是线程安全的,特殊,虽然他是共享变量(单例类级别的变量),但是springmvc底层 通过ThreadLocal来存储的servlet api,所以通过自动注入进来的servlet api是线程安全的。
3.通过@ModelAtrribute的方式
不是线程安全的,因为他是共享变量

7.使用forward实现页面转发

image.png
image.png
image.png


    //1。默认就是转发
    //2。可以显示加上forward进行转发,foward需要自己加上返回的完整视图逻辑名和路径,因为不会参与走视图解析器的解析
    @RequestMapping("/foward/test")
    public String forward(){
        return "forward:/login.jsp";
    }


    //重定向
    //必须加上redirect,不会参与走视图解析器的解析
    //注意:/会包含项目名称 springmvc 碰到redirect 自动会加上项目名称,Servlet要加上项目名称
    @RequestMapping("/redirect/test")
    public String redirect(){
        return "redirect:/login.jsp";
    }