天天看點

學習SpringMVC必知必會(3)~springmvc的請求和響應

一、處理器方法響應處理

▷ ​

​Controller方法該怎麼傳回、Controller資料該怎麼進行共享​

  • 傳回void/ModelAndView/String

1、Controller方法傳回void

//傳回void類型,此時可以把Controller方法當做Servlet使用【适合用來下載下傳檔案】
  @RequestMapping("/test1")
  public void test(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //請求轉發
    request.getRequestDispatcher("/WEB-INF/views/welcome.jsp").forward(request, response);
    //設定共享資料
    request.setAttribute("msg", "hello");
    //輸出json格式
    response.setContentType("text/json;charset=utf-8");
    response.getWriter().println();  
  }      

2、【​

​常用​

​】傳回ModelAndView

//傳回ModelAndView
  @RequestMapping("/test3")
  public ModelAndView test3() {
    ModelAndView mv = new ModelAndView();
    //設定視圖名稱
//    mv.setViewName("/WEB-INF/views/welcome.jsp");
    mv.setViewName("welcome");
    mv.addObject("msg", "傳回ModelNAndView");//設定共享資料的key和value
    mv.addObject("叩丁狼教育");//設定共享資料的value,此時會把value類型的首字母作為key:string
    return mv;
  }      

3、【​

​常用​

​​】傳回String類型(​

​是邏輯視圖名稱​

​​),參數是Model類型(​

​是共享資料​

​)

//傳回string,邏輯視圖名稱,此時需要結合參數Model類型 一起使用
  @RequestMapping("/test4")
  public String test4(Model model) {
    //設定共享資料
    model.addAttribute("叩丁狼");
    model.addAttribute("msg", "教育");
    return "welcome";//設定跳轉的視圖
  }      

二、請求跳轉

  • 請求轉發、URL重定向、URL重定向共享資料

1、請求轉發

//請求轉發,浏覽器位址欄不變,可以共享請求中的資料
  //原理:request.getRequestDispatcher("").forward(request, response);
  @RequestMapping("/test5")
  public String test5(Model model) {
    return "forward:/hello.jsp";//設定跳轉的視圖
  }      

2、URL重定向

//重定向,浏覽器位址欄改變,不能共享請求中的資料
  //原理:request.sendRedirect("");
  @RequestMapping("/test6")
  public String test6(Model model) {
    return "redirect:/hello.jsp";//設定跳轉的視圖
  }      

■ 請求資源的路徑問題:[總結:​

​通路資源的時候,都使用/開頭​

​]

  • 通路資源的時候前面帶上/,表示絕對路徑,從​

    ​根路徑​

    ​開始去尋找資源
  • 通路資源的時候簽名不加/,表示相對路徑,從​

    ​上一級上下文路徑​

    ​中去尋找資源

✿ 請求轉發和URL重定向的選擇:

請求轉發/URL重定向 請求轉發 URL重定向
位址欄改變? 不會 會改變
共享資料? 可以 不可以?
表單重複送出? 會發生 不會發生

傳統的方式,在url重定向的時候,因為是兩次不同的請求,是以不能共享請求中的資料。

在開發中,有時候真的需要重定向跳轉後共享資料------------spring3.1開始,提供了Flash屬性。
★ ​

​隻能是從Controller 重定向到 Controller,不能到jsp​

3、URL重定向共享資料

//重定向:從a跳轉到b  
  @RequestMapping("/a")
  public String a(RedirectAttributes ra) {
    ra.addAttribute("msg1", "a傳遞的資料");
    ra.addFlashAttribute("msg2", "msg2");
    return "redirect:/response/b";//設定跳轉的視圖
  }
  
  @RequestMapping("/b")
  public ModelAndView b(String msg1, @ModelAttribute("msg2") String msg2) {
    System.out.println("msg1:" + msg1);
    System.out.println("msg2:" + msg2);
    return null;
  }      

重定向共享資料的原理:更大的作用域--session

學習SpringMVC必知必會(3)~springmvc的請求和響應

三、處理器方法參數處理(​

​接收請求參數的處理​

​)

  • 處理器方法的請求參數該怎麼攜帶、請求參數該怎麼擷取

1、request 和 response 參數

■ 情況一:為了操作Servlet API 對象,此時可以直接以參數形式傳遞,也可以直接使用DI注入。

@Controller
@RequestMapping("/request")
public class HandlerRequestController {

  @Autowired
  private ServletContext context;
  
  @RequestMapping("/test1")
  public void test(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
    System.out.println("request:" + request);
    System.out.println("response:" + response);
    System.out.println("session:" + session);
    System.out.println("ServletContext:" + this.context);
    
  }
}      
  • request、response、session:建議使用參數
  • context 上下文:單例,建議使用屬性,注入

▷ ​

​因為Controller(Servlet) 是單例的,線程不安全,一般不用成員變量,​

​​

​除非要共享的資料,才作為成員變量。​

2、簡單類型參數

  • 處理簡單類型的請求參數

■ 擷取請求參數:【保證輸入的參數和定義的形參名稱一緻】

//擷取請求參數:通過保證請求參數名稱和Controller方法定義的形參(入參)同名即可
  @RequestMapping("/test2")
  public void test2(String username, int age)  {
    System.out.println(username);
    System.out.println(age);
  }      
學習SpringMVC必知必會(3)~springmvc的請求和響應

■ 擷取請求參數:【輸入的參數和定義的形參名稱不一緻】----注解​

​@RequestParam​

//擷取請求參數:若請求參數和請求參數名稱和形參不同----注解@RequestParam
  @RequestMapping("/test3")
  public void test3(@RequestParam("name") String username, @RequestParam(value="age",required=false) Integer age)  {
    System.out.println("username:" +username);
    System.out.println("age:" + age);
  }      

3、中文亂碼處理

■ 在"全局配置"【web.xml】,添加上​

​編碼過濾器​

​:

<filter>
    <filter-name>CharacterEncodingFilterfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    
    <init-param>
      <param-name>encodingparam-name>
      <param-value>utf-8param-value>
    init-param>
    <init-param>
      <param-name>forceRequestEncodingparam-name>
      <param-value>trueparam-value>
    init-param>
    <init-param>
      <param-name>forceResponseEncodingparam-name>
      <param-value>trueparam-value>
    init-param>
  filter>

  <filter-mapping>
    <filter-name>CharacterEncodingFilterfilter-name>
    <url-pattern>/*url-pattern>
  filter-mapping>      

4、restfull風格傳參

  • restfull 風格:軟體架構風格,嚴格講是一種編碼風格,充分利用http協定本身的語義,進而提供一些設計原則和限制條件,主要是用來作為用戶端和服務端的互動。
  • 簡潔、有層次、容易實作緩存機制
//restfull風格傳遞參數
  //PathVariable: 可以将url中占位符綁定到方法的形參中
  @RequestMapping("/r/{id}")
  public ModelAndView rest(@PathVariable("id") Integer id) {
    System.out.println("id:" + id);
    return null;
  }      

5、數組和List類型參數

//接收一個參數有很多值的情況
  //使用數組:可以直接接收  Long[] ids
  //使用List: 不可以直接接收,可以在對象中存在一個集合   List ids
  @RequestMapping("/batchDelete") //batchDelete?ids=10&ids=20&ids=30
  public void batchDelete(FormBean fb) {
    System.out.println(fb.getIds());  
  }      
★ 操作一個參數有多個值的情況,一般直接使用數組接收即可,或者使用javaBean對象來封裝資料。

6、■ 擷取請求參數:

JavaBean類型參數【​

​将請求參數封裝成一個對象​

​】

//封裝成一個對象
  @RequestMapping("/bean") //batchDelete?ids=10&ids=20&ids=30
  public void bean(User user) {
    System.out.println(user);  
  }      
  • 請求參數封裝成javaBean對象,浏覽器位址欄直接輸入參數為對象的屬性即可.
學習SpringMVC必知必會(3)~springmvc的請求和響應

✿ 總結處理器方法參數處理:

1、​

​直接把請求參數封裝成javaBean對象​

2、配置解決中文亂碼的過濾器
3、簡單類型參數----輸入參數名和定義的形參不同-> @ResultParam
4、使用​

​數組​

​接收多個參數
5、restfull風格傳參

四、ModelAttribute

  • 給共享的model資料設定key名,貼在形參上,也可以貼在方法上,

    針對複合類型參數,預設情況下就會放到model中(共享), 預設的key就是類型首字母小寫

  • 使用注解@ModelAttribute,起個别名
//ModelAttribute注解:
  /*
   *1、給共享的model資料設定key名,貼在形參上,也可以貼在方法上
   * 針對複合類型(非簡單類型)參數,預設情況下就會放到model中(共享), 預設的key就是類型首字母小寫
   * 2、可以标注一個非請求處理的方法,被标注的方法,每次在請求處理方法之前都會優先被執行[存放多個請求需要共享的資料]
   */
  @RequestMapping("/test11")
  public String test1(@ModelAttribute("u") User user)  {
    System.out.println(user);
    return "welcome";
  }      

五、其他請求資訊

1、擷取請求頭 ​

​@RequestHeader​

@RequestMapping("/test1")
  public ModelAndView test1(@RequestHeader("User-Agent") String userAgent) {
    System.out.println("test1");
    System.out.println("User-Agent:" + userAgent);
    return null;
  }      

2、擷取Cookie ​

​@CookieValue​

@RequestMapping("/test1")
  public ModelAndView test1(@RequestHeader("User-Agent") String userAgent, @CookieValue("Webstorm-5895a979") String cName) {
    System.out.println("test1");
    System.out.println("User-Agent:" + userAgent);
    System.out.println("cName:" + cName);
    return null;
  }      

3、操作HttpSession ​

​@SessionAttributes​

  • 預設情況下模型資料是儲存到 request 作用域的
@Controller
@RequestMapping("/other")
@SessionAttributes("errMsg")
public class OtherController {

  @RequestMapping("/test2")
  public String test2(Model model) {
    System.out.println("操作session");
    model.addAttribute("errMsg", "錯誤資訊");
    return "redirect:/hello.jsp";
  }
}      

六、資料綁定流程

學習SpringMVC必知必會(3)~springmvc的請求和響應

1、架構把 ServletRequest 對象和請求參數傳遞給 ​

​DataBinder​

​;

2、DataBinder 首先調用 Spring Web 環境中的 ConversionService 元件,進行資料類型轉換和格式化等操作,将 ServletRequest 中的資訊填充到形參對象中;

3、DataBinder 然後調用 Validator 元件對已經綁定了請求消息資料的形參對象進行資料合法性校驗;

4、DataBinder 最後輸出資料綁定結果對象 BindingResult

  • BindingResult 包含了已完成資料綁定的形參對象和校驗錯誤資訊對象

七、多對象封裝傳參

/*
   * 需要吧表單資料封裝到多個對象中去,若各個對象有相同的屬性時
   * 不知道該把哪一個參數封裝到哪一個對象
   */
  @RequestMapping("/save")
  public ModelAndView save(Cat cat, Dog dog) {
    System.out.println("送出資料");
    System.out.println(cat);
    System.out.println(dog);
    return null;
  }      
  • input.jsp 傳遞多個對象的參數時:

貓名:

貓年齡:

狗名:

狗年齡:

學習SpringMVC必知必會(3)~springmvc的請求和響應

解決:

input.jsp:加上字首做區分

貓名:

貓年齡:

狗名:

狗年齡:

  • 處理器Controller添加方法:
//從參數--> 對象,封裝規則需要我們來設定
  
  //自定義資料綁定注冊,将請求參數轉化成對應對象的屬性
  @InitBinder("cat")
  public void initBinderCat(WebDataBinder binder) {
    //設定字段以什麼做為字首
    binder.setFieldDefaultPrefix("cat.");
  }
  
  @InitBinder("dog")
  public void initBinderDog(WebDataBinder binder) {
    //設定字段以什麼做為字首
    binder.setFieldDefaultPrefix("dog.");
  }      
學習SpringMVC必知必會(3)~springmvc的請求和響應

八、JSON資料處理

  • JSON處理

1、依賴:

  • jackson-annotations-2.12.2.jar
  • jackson-core-2.12.2.jar
  • jackson-databind-2.12.2.jar

2、處理json的注解 ​

​@ResponseBody​

​​ ​

​@RestController​

​​ ​

​@RequestBody​

(1) @ResponseBody: 處理響應,把對象轉化成json字元串

  • @ResponseBody 處理響應,把對象轉化成json字元串
  • 貼到方法上:隻會針對目前方法做json處理
  • 貼到類上:會對目前類中所有方法做json處理
//把單個對象/Map轉化成json格式
  @RequestMapping("/test1")
  @ResponseBody
  public User test1() {
    User u = new User();
    u.setUsername("shan");
    u.setAge(18);
    return u;
  }
  
  //把多個對象轉化成json格式
  @RequestMapping("/test2")
  @ResponseBody
  public List<User> test2() {
    User u = new User();
    u.setUsername("shan");
    u.setAge(18);
    return Arrays.asList(u, u, u);
  }


  //傳回一個String,預設傳回字元串是邏輯視圖名稱,加上@ResponseBody,當做json格式的資料
  @RequestMapping(value="/test3", produces="application/json;charset=utf-8")
  @ResponseBody
  public String test3() {
    return "success, 你好~";
  }      

(2) @RestController = @Controller + @ResponseBody

(3) @RequestBody

  • @RequestBody: 處理請求,用于讀取Http請求的内容,把json格式的請求資料封裝成對象
  • application/x-www-form-urlencoded: 表單送出用得比較多,是傳統的key-value格式,處理起來非常友善,無需RequestBody都可以,貼上也可以
  • application/multipart: 檔案上傳的請求,springmvc 裝飾設計模式,既可以處理檔案上傳,也可以處理表單資料
  • application/json: 參數是json格式的,此時必須使用RequestBody\
  • application/xml

九、日期類型處理

1、前台往背景傳參轉化為Date類型

★ 時間格式的注解:@DateTimeFormat

  • 注意細節:時間Date在util包(java中常用)有,在sql包也有,使用快捷鍵導包的時候可能會預設自動報錯包~
//從前台---->背景傳遞參數 java.lang.String -> java.util.Date
  //請求參數是Date類型
  @RequestMapping("/test1")
  public ModelAndView test(@DateTimeFormat(pattern = "yyyy-MM-dd")Date date) {
    System.out.println("date:" + date);
    if(date instanceof Date) {
      System.out.println("yes");
    }
    return null;
  }      
  • 對象的屬性有時間Date類型的,方式一:貼注解 @DateTimeFormat

    ◆ 方式二:資料綁定的時候處理,通過@InitBinder定義處理時間格式的方法

@InitBinder
  public void initBinder(WebDataBinder binder) {
    //日期格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    //屬性編輯器
    binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
  }      
  • 讓項目中的所有用到時間格式的類都使用到咱定義的處理時間格式的方法,咱将方法抽離出去,定義成一個類,貼上注解處理增強​

    ​@ControllerAdvice​

    ​,

    隻要抽離的類在ioc的注解驅動掃描範圍内,即可~

@ControllerAdvice
public class DateFormateAdvice {

  @InitBinder
  public void initBinder(WebDataBinder binder) {
    //日期格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    //屬性編輯器
    binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
  }
}      

2、jsp中顯示時間格式:将歐美時間格式-->中國時間格式

(1)導入jar包[tomcat伺服器examples案例下的lib就有]:

  • taglibs-standard-impl-1.2.5.jar
  • taglibs-standard-spec-1.2.5.jar

(2)配置引入标簽庫taglib

<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>      

(3) 使用jstl:

<% pageContext.setAttribute("myDate", new java.util.Date()); %> 
  中原標準時間:       
學習SpringMVC必知必會(3)~springmvc的請求和響應

3、背景往前台響應JSON時---Date類型

(1)方法1:在springmvc架構配置中添加json類型轉化相關的配置[配置全局解析器]:

<mvc:annotation-driven>
    <mvc:message-converters>
      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="objectMapper">
          <bean class="com.fasterxml.jackson.databind.ObjectMapper">
            <property name="dateFormat">
              <bean class="java.text.SimpleDateFormat">
                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
              bean>
            property>
          bean>
        property>
      bean>
    mvc:message-converters>
  mvc:annotation-driven>      

(2)方式2:使用注解@JsonFormat

@Data
public class User {
  private Long id;
  private String username;
  private Integer age;
  //@DateTimeFormat(pattern = "yyyy-MM-dd")
  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  private Date hireDate;  
}      

★ 注意:​

​@DateTimeFormat​

​ 是前台往背景傳參【前台String類型-》背景Date類型】

★ 注意: 是背景響應給前台,響應為json格式(對時間Date類型的處理)

如果本文對你有幫助的話記得給一樂點個贊哦,感謝!