国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

SpringMVC入門筆記

gekylin / 2455人閱讀

摘要:簡介注解用于修飾的方法,根據(jù)的的內(nèi)容,通過適當?shù)霓D(zhuǎn)換為客戶端需要格式的數(shù)據(jù)并且寫入到的數(shù)據(jù)區(qū),從而不通過視圖解析器直接將數(shù)據(jù)響應給客戶端。并且這些解析器都實現(xiàn)了接口,在接口中有四個最為主要的接口方法。

SpringMVC 細節(jié)方面的東西很多,所以在這里做一篇簡單的 SpringMVC 的筆記記錄,方便以后查看。

Spring MVC是當前最優(yōu)秀的MVC框架,自從Spring 2.5版本發(fā)布后,由于支持注解配置,易用性有了大幅度的提高。Spring 3.0更加完善,實現(xiàn)了對老牌的MVC框架Struts 2的超越,現(xiàn)在版本已經(jīng)到了Spring5.x了。

一、工程創(chuàng)建 1.添加架包

創(chuàng)建Maven的web工程,添加依賴架包

Maven架包添加 spring-contextspring-webspring-webmvclog4j

2.web.xml配置

在web.xml中配置DispatcherServlet


  dispatcherServlet
  org.springframework.web.servlet.DispatcherServlet
  
    contextConfigLocation
    classpath:spring-mvc.xml
  
  1



  dispatcherServlet
  /

注意:這里配置的 / 攔截資源配置的是 /,攔截所有除其他 servlet 之外的資源訪問,包括 jsp、靜態(tài)網(wǎng)頁、圖片等等。與 /* 不一樣,/* 一般配在攔截器里面,攔截所有資源訪問。

3.創(chuàng)建SpringMVC的配置文件

上面配置 DispatcherServlet 里面用到了 contextConfigLocation 配置文件的地址,下面來創(chuàng)建配置文件。




    
    

    
    

    
    

    
    
        
        
    

    
    

二、@RequestMapping 注解

在對 SpringMVC 進行的配置的時候, 需要我們指定請求與處理方法之間的映射關系。 指定映射關系,就需要我們用上 @RequestMapping 注解。
@RequestMapping 是 Spring Web 應用程序中最常被用到的注解之一,這個注解會將 HTTP 請求映射到控制器(Controller類)的處理方法上。

1.value和method屬性

簡單例子

@RequestMapping("rm")
@Controller
public class RequestMappingController {

    @RequestMapping(value = {"home", "/", ""}, method = RequestMethod.GET)
    public String goRMHome() {
        System.out.println("訪問了 Test RequestMapping 首頁");
        return "1-rm";
    }
}

最終訪問路徑是 .../rm/home,通過該方法返回視圖名字和SpringMVC視圖解析器加工,最終會轉(zhuǎn)發(fā)請求到 .../WEB-INF/jsp/1-rm.jsp 頁面。
如果沒有類名上面的 @RequestMapping("rm"),則訪問路徑為 .../home
method 指定方法請求類型,取值有 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE。
value 為數(shù)組字符串,指定訪問路徑與方法對應,指定的地址可以是URI。URI值可以是中:普通的具體值、包含某變量、包含正則表達式。

下面以包含某一變量舉例:

@RequestMapping(value = "testPathVariable/{username}", method = RequestMethod.GET)
public String testPathVariable(@PathVariable(value = "username") String name) {
    //參數(shù)部分也可以直接寫成 @PathVariable String username, 省略value, 保證形參名與上面 {} 內(nèi)的名字一致
    //不建議省略
    System.out.println("訪問了 Test PathVariable 方法 username: " + name);
    return "success";
}
2.consumes屬性

指定處理請求的提交內(nèi)容類型(Content-Type)

@RequestMapping(value = "testConsumes", method = RequestMethod.POST, consumes = "application/x-www-form-urlencoded")
public String testConsumes() {
    System.out.println("訪問了 Test Consumes 方法");
    return "success";
}

如果請求里面的 Content-Type 對不上會報錯

3.produces屬性

指定返回的內(nèi)容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回

其中 */*;q=0.8 表明可以接收任何類型的,權重系數(shù)0.8表明如果前面幾種類型不能正常接收則使用該項進行自動分析。

@RequestMapping(value = "testProduces", method = RequestMethod.POST, produces = "text/html")
public String testProduces() {
    return "success";
}
4.params屬性

指定request中必須包含某些參數(shù)值,才讓該方法處理

JSP頁面請求

用戶名:
密 碼:

Controller 里面對應的請求方法

@RequestMapping(value = "testParams", method = RequestMethod.POST, params = {"username!=Tom", "password"})
public String testParams() {
    return "success";
}

params = {"username!=Tom", "password"} 表示請求參數(shù)里面 username !=Tom 且有包含 password,二者有一個不滿足則會報錯

5.headers屬性

指定 request 中必須包含某些指定的 header 值,才能讓該方法處理請求

@RequestMapping(value = "testHeaders", method = RequestMethod.GET, headers = "Accept-Language=zh-CN,zh;q=0.9")
public String testHeaders() {
    return "success";
}

如果跟設定頭里面對不上會報404錯誤

三、@RequestParam注解

請求

單參數(shù) GET 請求方式
1.省略注解

表單元素的name名字和控制器里的方法的形參名一致,此時可以省略 @RequestParam 注解

@RequestMapping(value = "testGetOneParam", method = RequestMethod.GET)
public String testGetOneParam(String username) {
    System.out.println("訪問了 單參數(shù) Get 請求方法 username: " + username);
    return "success";
}
2.不省略注解

示例

@RequestMapping(value = "testPostOneParam", method = RequestMethod.POST)
public String testPostOneParam(@RequestParam String username) {
    System.out.println("username: " + name);
    return "success";
}

參數(shù)名字不一致時

@RequestMapping(value = "testPostOneParam", method = RequestMethod.POST)
public String testPostOneParam(@RequestParam(value = "username", required = false, defaultValue = "") String name) {
    System.out.println("username: " + name);
    return "success";
}

value 屬性指定傳過來的參數(shù)名,跟方法里的形參名字對應上
required 指定該參數(shù)是否是必須攜帶的
defaultValue 沒有或者為 null 時,指定默認值

注:省略和不省略 @RequestParam 注解,最終SpringMVC內(nèi)部都是使用 RequestParamMethodArgumentResolver 參數(shù)解析器進行參數(shù)解析的。如果省略 @RequestParam 注解或省略 @RequestParam 注解的 value 屬性則最終則以形參的名字作為 keyHttpServletRequest 中取值。

四、@RequestHeader 和 @CookieValue 注解

@RequestHeader 注解:可以把 Request 請求 header 部分的值綁定到方法的參數(shù)上

@RequestMapping(value = "rh")
@Controller
public class RequestHeaderController {

    @RequestMapping(value = "testRHAccept", method = RequestMethod.GET)
    public String testRHAccept(@RequestHeader(value = "Accept") String accept) {
        System.out.println(accept);
        return "success";
    }

    @RequestMapping(value = "testRHAcceptEncoding", method = RequestMethod.GET)
    public String testRHAcceptEncoding(@RequestHeader(value = "Accept-Encoding") String acceptEncoding) {
        System.out.println(acceptEncoding);
        return "success";
    }
}

@CookieValue 注解:可以把Request header中關于cookie的值綁定到方法的參數(shù)上

@RequestMapping(value = "cv")
@Controller
public class CookieValueController {
    @RequestMapping(value = "testGetCookieValue", method = RequestMethod.GET)
    public String testGetCookieValue(@CookieValue(value = "JSESSIONID") String cookie) {
        System.out.println("獲取到Cookie里面 JSESSIONID 的值 " + cookie);
        return "success";
    }
}
五、數(shù)據(jù)結(jié)果封裝 ModelAndView & ModelMap & Map & Model

SpringMVC 為了方便數(shù)據(jù)封裝和處理,提供了以下幾種方案,最終會將封裝到模型里面的數(shù)據(jù)全都通過 request.setAttribute(name, value) 添加request請求域中。

1.ModelAndView

使用 ModelAndView 類用來存儲處理完后的結(jié)果數(shù)據(jù),以及顯示該數(shù)據(jù)的視圖。從名字上看 ModelAndView 中的 Model 代表模型,View 代表視圖。model ModelMap 的類型,而 ModelMap 又是 LinkedHashMap 的子類,view 包含了一些視圖信息。

@RequestMapping(value = "testReturnModelAndView", method = RequestMethod.GET)
public ModelAndView testReturnModelAndView() {

    Student s1 = new Student(1, "Tom", 13, new Date());
    Student s2 = new Student(2, "Jerry", 14, new Date());

    List list = new ArrayList<>();
    list.add(s1); list.add(s2);

    HashMap map = new HashMap<>();
    map.put("s1", s1); map.put("s2", s2);

    ModelAndView mv = new ModelAndView();
    mv.addObject("s1", s1);
    mv.addObject("s2", s2);

    mv.addObject("list", list);
    mv.addObject("map", map);
    mv.setViewName("5-m&v-success");
    return mv;
}
2.ModelMap & Map & Model

最終也是將封裝的數(shù)據(jù)和返回視圖名字封裝成 ModelAndView對象

@RequestMapping(value = "testMapParam", method = RequestMethod.GET)
public String testMapParam(Map paramMap) {
    ...
    paramMap.put("s1", s1);
    paramMap.put("s2", s2);

    paramMap.put("list", list);
    paramMap.put("map", map);
    return "5-m&v-success";
}

@RequestMapping(value = "testModelParam", method = RequestMethod.GET)
public String testModelParam(Model model) {
    ...
    model.addAttribute("s1", s1);
    model.addAttribute("s2", s2);

    model.addAttribute("list", list);
    model.addAttribute("map", map);
    return "5-m&v-success";
}

@RequestMapping(value = "testModelMapParam", method = RequestMethod.GET)
public String testModelMapParam(ModelMap modelMap) {
    ...
    modelMap.addAttribute("s1", s1);
    modelMap.addAttribute("s2", s2);

    modelMap.addAttribute("list",list);
    modelMap.addAttribute("map", map);
    return "5-m&v-success";
}
3.JSP頁面提取數(shù)據(jù)
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



    
        

單個數(shù)據(jù)封裝

s1
姓名${s1.name}
年齡${s1.age}
生日${s1.birthday.toString()}
s2
姓名${s2.name}
年齡${s2.age}
生日${s2.birthday.toString()}

List數(shù)據(jù)封裝

${status.count}
姓名${s.name}
年齡${s.age}
生日${s.birthday.toString()}

Map數(shù)據(jù)封裝

${node.key}
姓名${node.value.name}
年齡${node.value.age}
生日${node.value.birthday.toString()}
六、@SessionAttributes

如果我們希望在多個請求之間共用某個模型屬性數(shù)據(jù),則可以在控制器類上標注一個 @SessionAttributes,SpringMVC 將把模型中對應的屬性暫存到 HttpSession 的域中。

使用方法:
@SessionAttributes(value={"xxx"}, types={xxxx.class})
value:是通過鍵來指定放入HttpSession 的域中的值;
types:是通過類型指定放入HttpSession 的域中的值;

@SessionAttributes(types=Student.class)
這個注解會將類中所有放入 Request 域中的 Student 對象同時放進 HttpSession 的域空間中。

可以添加多個屬性
@SessionAttributes(value={“s1”, “s2”})
@SessionAttributes(types={User.class, Grade.class})

可以混合使用
@SessionAttributes(value={“s1”, “s2”},types={Grade.class})

示例

//@SessionAttributes(value = {"s1", "s2"})
@SessionAttributes(types = Student.class)
@RequestMapping(value = "sa")
@Controller
public class SessionAttributesController {

    @RequestMapping(value = "testSA", method = RequestMethod.GET)
    public String testSessionAttributes(Model model) {
        Student s1 = new Student(1, "Tom", 13, new Date());
        Student s2 = new Student(2, "Jerry", 13, new Date());

        model.addAttribute("s1", s1);
        model.addAttribute("s2", s2);
        return "6-sa-success";
    }
}

JSP 頁面提取數(shù)據(jù)

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" isELIgnored="false" %>


    request s1 : ${requestScope.get("s1")}

request s2 : ${requestScope.get("s2")}

session s1 : ${sessionScope.get("s1")}

session s2 : ${sessionScope.get("s2")}

七、@ModelAttribute

該注解平時使用的比較多,不僅可以寫在方法上面也可以寫在參數(shù)前面。

1.寫在方法上面

在同一個控制器中,標注了@ModelAttribute 的方法實際上會在 @RequestMapping 注解方法之前被調(diào)用。

標注了@ModelAttribute 的方法能接受與@RequestMapping 標注相同的參數(shù)類型,只不過不能直接被映射到具體的請求上。

標注在方法上的 @ModelAttribute 說明方法一般是用于添加一個或多個屬性到 model 上。

模擬請求

模擬請求
① 省略 value 屬性值手動加入屬性
@ModelAttribute
public void modelAttributeMethod1(ModelMap modelMap) {
    Person person = new Person("超哥哥 1 號", 12);
    modelMap.addAttribute("person1", person);
}

@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(ModelMap modelMap) {
    modelMap.forEach((key, value) -> {
        System.out.println(key + " = " + value);
        //person1 = Person{name="超哥哥 1 號", age=12}
    });
    return "success";
}

可以看出手動加入 model 里面屬性成功,key 為自定義的字符串。

② 省略 value 屬性值自動加入屬性
@ModelAttribute
public Person modelAttributeMethod2() {
    return new Person("超哥哥 2 號", 12);
}

@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(ModelMap modelMap) {
    modelMap.forEach((key, value) -> {
        System.out.println(key + " = " + value);
        //person = Person{name="超哥哥 2 號", age=12}
    });
    return "success";
}

可以看出 @ModelAttribute 修飾的方法沒有指定 value 屬性時,讓其自動加入的 key 是以添加類的類名首字母小寫。

③ 指明 value 屬性值自動加入屬性
@ModelAttribute(value = "person3")
public Person modelAttributeMethod3() {
    return new Person("超哥哥 3 號", 13);
}

@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(ModelMap modelMap) {
    modelMap.forEach((key, value) -> {
        System.out.println(key + " = " + value);
        //person3 = Person{name="超哥哥 3 號", age=13}
    });
    return "success";
}

從上面可以看出 @ModelAttribute 修飾的方法有指定 value 屬性時,讓其自動加入的 key 就是自定的 value 屬性的值。

2.寫在參數(shù)前面

標注在方法參數(shù)前的 @ModelAttribute 說明了該方法參數(shù)的值將由 model 中取得,如果 model 中找不到,那么該參數(shù)會先被實例化,然后被添加到 model 中。在 model 中存在以后,將請求中所有名稱匹配的參數(shù)都填充到該參數(shù)對象上。

模擬請求

模擬請求
① 省略 value 屬性值自動匹配或創(chuàng)建
@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(@ModelAttribute Person person) {
    System.out.println(person);
    //Person{name="null", age=13}
    return "success";
}

注:在執(zhí)行 testModelAttribute(..) 方法時,因為參數(shù)屬性是一個 Person 類對象,那么他先從 model 里面找(沒有指明 value 屬性值,則以該類名首字母小寫為 key),發(fā)現(xiàn)找不到便創(chuàng)建一個,把請求里面的參數(shù)賦值到該創(chuàng)建對象上,找到了則用請求里面的參數(shù)更新該對象。

② 指定 value 屬性值匹配或創(chuàng)建
@ModelAttribute(value = "p")
public Person modelAttributeMethod3(@RequestParam Integer age) {
    return new Person("超哥哥 3 號", age);
}

@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(@ModelAttribute(value = "p") Person person) {
    System.out.println(person);
    //Person{name="超哥哥 3 號", age=13}
    return "success";
}

注:在執(zhí)行 testModelAttribute(..) 方法時,因為參數(shù)屬性是一個 Person 類對象,那么他先從 model 里面找(有指明 value 屬性值,則以 value 屬性值為 key),發(fā)現(xiàn)找不到便創(chuàng)建一個,把請求里面的參數(shù)賦值到該創(chuàng)建對象上,找到了則用請求里面的參數(shù)更新該對象。

③ 省略 @ModelAttribute 注解的 POJO 參數(shù)
@ModelAttribute
public Person modelAttributeMethod3(@RequestParam Integer age) {
    return new Person("超哥哥 4 號", age);
}

@RequestMapping(value = "testModelAttribute", method = RequestMethod.GET)
public String testModelAttribute(Person person) {
    System.out.println(person);
    //Person{name="超哥哥 4 號", age=13}
    return "success";
}

注:@ModelAttribute 注解修飾的方法,沒有指定 value 屬性,則自動注入到 model 里面的 value 以該對象類名首字母小寫為 key。在下面 @RequestMapping 修飾的方法 testModelAttribute(..) 參數(shù)時一個 POJO 對象,雖前面沒有注解修飾,但默認也會去匹配 ModelAttributeMethodProcessor 參數(shù)解析器去解析該參數(shù),說白了與上面的第一種情況 @ModelAttribute 注解修飾沒有設置 value 屬性值是一樣的。

八、在Controller中使用redirect方式處理請求

forword:表示轉(zhuǎn)發(fā)!
redirect:表示重定向!

@RequestMapping(value = "index")
public String index() {
    return "success";
}
@RequestMapping(value = "index")
public String index() {
    return "redirect:success";
}
九、RESTFul 風格的 SpringMVC 1.RESTFulController
@RequestMapping(value = "rest")
@Controller
public class RESTFulController {

    @RequestMapping(value = {"home", "/", ""}, method = RequestMethod.GET)
    public String goResetHome() {
        System.out.println("訪問了 Rest 風格測試首頁");
        return "8-rest";
    }

    @RequestMapping(value = "student/{id}", method = RequestMethod.GET)
    public String get(@PathVariable(value = "id") Integer id) {
        System.out.println("get " + id);
        return "success";
    }

    @RequestMapping(value = "student/{id}", method = RequestMethod.POST)
    public String post(@PathVariable(value = "id") Integer id) {
        System.out.println("post " + id);
        return "success";
    }

    @RequestMapping(value = "student/{id}", method = RequestMethod.PUT)
    public String put(@PathVariable(value = "id") Integer id) {
        System.out.println("put " + id);
        return "success";
    }

    @RequestMapping(value = "student/{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable(value = "id") Integer id) {
        System.out.println("delete " + id);
        return "success";
    }
}
2.web.xml中配置

form表單發(fā)送put和delete請求,需要在web.xml中進行如下配置



  hiddenHttpMethodFilter
  org.springframework.web.filter.HiddenHttpMethodFilter


  hiddenHttpMethodFilter
  /*
3.模擬請求
十、@RequestBody 和 @ResponseBody

在SpringMVC的 Controller 中經(jīng)常會用到 @RequestBody@ResponseBody 這兩個注解,若想使用這兩個注解,前提要寫好 標簽,他會幫我們注入接下里解析需要的轉(zhuǎn)換器。

1.@RequestBody

簡介:
@RequestBody 注解用于修飾 Controller 的方法參數(shù),根據(jù) HTTP Request Header 的 content-Type 的內(nèi)容,通過適當?shù)?HttpMessageConverter 轉(zhuǎn)換為 Java 類。

使用時機:
當提交的數(shù)據(jù)不是普通表單的形式(application/x-www-form-urlcodedmultipart/form-data),而是 JSON 格式(application/json) 或 XML 格式(application/xml)。

使用示例:XML格式數(shù)據(jù)提交

POJO 模型類

@XmlRootElement(name = "person")
public class Person {
    private String name;
    private Integer age;

    public String getName() { return name; }
    @XmlElement
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    @XmlElement
    public void setAge(Integer age) { this.age = age; }
}

AJAX 請求

點擊事件

Controller 里對應的方法

@RequestMapping(value = "testRequestBody", method = RequestMethod.POST)
public String testRequestBody(@RequestBody Person person) {
    System.out.println(person);
    //Person{name="Tom", age=13}
    return "success";
}

注:@RequestBody 注解對于XML請求數(shù)據(jù)的解析,請求方要指定 Content-Type = application/xml;charset=utf-8,服務器如果要將接收數(shù)據(jù)封裝成 POJO 類,需要在該 POJO 類里面用 @XmlRootElement@XmlElement 注解指明跟標簽和子標簽,SpringMVC 內(nèi)部最終用到的是自帶的 Jaxb2RootElementHttpMessageConverter 轉(zhuǎn)換器(其實現(xiàn)了 HttpMessageConverter 接口)。

2.@ResponseBody

簡介:
@ResponseBody 注解用于修飾 Controller 的方法,根據(jù) HTTP Request Header 的 Accept 的內(nèi)容,通過適當?shù)?HttpMessageConverter 轉(zhuǎn)換為客戶端需要格式的數(shù)據(jù)并且寫入到 Responsebody 數(shù)據(jù)區(qū),從而不通過視圖解析器直接將數(shù)據(jù)響應給客戶端。

使用時機:
返回的數(shù)據(jù)不是html標簽的頁面,而是其他某種格式的數(shù)據(jù)時(如json、xml等)使用。

使用示例:XML格式數(shù)據(jù)響應

POJO 模型類

@XmlRootElement(name = "person")
public class Person {
    private String name;
    private Integer age;

    public String getName() { return name; }
    @XmlElement
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    @XmlElement
    public void setAge(Integer age) { this.age = age; }
}

Controller 里對應的方法

@ResponseBody
@RequestMapping(value = "testRequestBody", method = RequestMethod.POST)
public Person testRequestBody() {
    Person person = new Person("Tom",13);
    return person;
}

AJAX 請求

點擊事件

最終瀏覽器控制臺輸出

注:@ResponseBody 注解對于響應XML格式數(shù)據(jù)的解析,請求方要指定 Accept = application/xml;charset=utf-8,服務器如果想將 POJO 類轉(zhuǎn)換成XML格式數(shù)據(jù),需要在該 POJO 類里面用 @XmlRootElement@XmlElement 注解指明跟標簽和子標簽,SpringMVC 內(nèi)部最終用到的是自帶的 Jaxb2RootElementHttpMessageConverter 轉(zhuǎn)換器(其實現(xiàn)了 HttpMessageConverter 接口)。

3.原理簡介

@RequestBody@ResponseBody 注解最終匹配到的參數(shù)解析器和返回值解析器都是 RequestResponseBodyMethodProcessor 對象,所以該對象分別實現(xiàn)了 HandlerMethodArgumentResolverHandlerMethodReturnValueHandler 接口。
在該解析器中有一個 messageConverters 屬性,該屬性是用來記錄轉(zhuǎn)換器的 List,這些轉(zhuǎn)換器都是在該解析器初始化的時候 標簽幫我們注入的。并且這些解析器都實現(xiàn)了 HttpMessageConverter 接口,在 HttpMessageConverter 接口中有四個最為主要的接口方法。

public interface HttpMessageConverter {
    boolean canRead(Class clazz, @Nullable MediaType mediaType);
    T read(Class clazz, HttpInputMessage inputMessage);

    boolean canWrite(Class clazz, @Nullable MediaType mediaType);
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage);
}

read 對應請求輸入的轉(zhuǎn)換解析,write 對應響應輸出的轉(zhuǎn)換解析。
canRead 根據(jù) Request Header 的 content-Type 的內(nèi)容查看該 HttpMessageConverter 換器是否支持轉(zhuǎn)換,支持則轉(zhuǎn)換為對應的 Java 類綁定到修飾的方法入?yún)⑸稀?br>canWrite 根據(jù) Request Headers 里面的 Accept 的內(nèi)容查看該 HttpMessageConverter 換器是否支持轉(zhuǎn)換,支持則轉(zhuǎn)換成指定格式后,寫入到 Response 對象的 body 數(shù)據(jù)區(qū)。

對應流程圖如下

十一、解析和返回 Json 數(shù)據(jù) 1.支持架包導入

首先需要導入 JSON 支持架包并且注入轉(zhuǎn)換器


  com.fasterxml.jackson.core
  jackson-databind
  2.9.6

jackson-databind-2.9.6.jar 架包依賴于 jackson-annotations-2.9.0.jarjackson-core-2.9.6.jar,所以省略了依賴架包的手動導入。

同時要寫好 標簽,其會幫我們注入對應的JSON數(shù)據(jù)轉(zhuǎn)換器。

2.代碼示例

需要封裝的 POJO

public class Person {
    private String name;
    private Integer age;
}

Controller中對應的請求方法

@ResponseBody
@RequestMapping(value = "testRequestBody", method = RequestMethod.POST)
public Person testRequestBody(@RequestBody Person person) {
    System.out.println(person);
    return person;
}

注:參數(shù)用 @RequestBody 修飾意思是將請求的JSON數(shù)據(jù)用合適的轉(zhuǎn)換器,轉(zhuǎn)換成 Java 類。@ResponseBody 注解是將返回的數(shù)據(jù)通過合適的轉(zhuǎn)換器轉(zhuǎn)換成客戶端想要的樣子并返回,在這里是將請求解析的 Person 對象轉(zhuǎn)換成JOSN格式數(shù)據(jù)并返回。

AJAX 請求

點擊事件

注:① 發(fā)送的數(shù)據(jù)要是JSON格式(也就是 data 屬性的數(shù)據(jù)是JSON格式);② 指明請求數(shù)據(jù)為JSON格式(contentType: "application/json;charset=utf-8");③ 指明接收數(shù)據(jù)為JSON格式(headers: { Accept: "application/json;charset=utf-8" })。

3. 原理簡介

最終使用到的轉(zhuǎn)換器是 jackson 提供的 MappingJackson2HttpMessageConverter,也是在解析器初始化的時候 標簽幫我們注入的。

十二、文件上傳 1.支持架包導入

為了實現(xiàn)文件上傳,需要導入 commons-fileupload 架包,導入如下



    commons-fileupload
    commons-fileupload
    1.3.3
2.配置MultipartResolver

SpringMVC 上下文中默認沒有裝配 MultipartResolver,因此默認情況下其不能處理文件上傳工作。如果想使用SpringMVC的文件上傳功能,則需要在上下文中配置 MultipartResolver。在SpringMVC配置文件中進行如下配置


    
    
    
    

注:這里一定要設置 id,并且值必須是 multipartResolver,下面的簡單原理會解釋。

3.代碼示例

Controller 中對應的方法

@RequestMapping(value = "upload", method = RequestMethod.POST)
public String testUpload(@RequestParam(value = "file") MultipartFile multipartFile, HttpServletRequest request) throws Exception {
    if (multipartFile.isEmpty() == false) {
        //multipartFile.getName()   標簽名字
        //multipartFile.getOriginalFilename()  上傳文件名字
        //multipartFile.getSize()   上傳文件大小
        //multipartFile.getContentType()    上傳文件類型

        //在 webapp 目錄下面(項目目錄下面) 建立一個 resources 資源文件夾, 用來存儲上傳的資源文件
        String parent = request.getServletContext().getRealPath("/resources");
        String filename = UUID.randomUUID() + multipartFile.getOriginalFilename();

        File file = new File(parent, filename);
        multipartFile.transferTo(file);
    }
    return "success";
}

JSP頁面的可變表單請求


4.原理簡介

DispatcherServlet 初始化的時候,會從容器中加載 MultipartResolver 可變表單解析器,從下面源碼中可以看出加載條件就是 idname 為 multipartResolver 的 bean

接著簡單了解下解析,在 DispatcherServletdoDispatch(..) 方法中檢查該請求是否是可變表單請求,如果是則用加載到緩存的 MultipartResolver 解析器 (這里用到的是注入容器中的 CommonsMultipartResolver 可變表單解析器,其實現(xiàn)了 MultipartResolver 接口) 將可變請求解析成 MultipartFile 對象 (這里是 CommonsMultipartFile,其實現(xiàn)了MultipartFile 接口),放在 HttpServletRequest 對象中,最終通過合適的參數(shù)解析器綁定到對應方法的參數(shù)上。

十三、文件下載

SpringMVC提供了一個 ResponseEntity 類型,使用它可以很方便地定義返回的 HttpHeadersHttpStatus
以下代碼演示文件的下載功能

@RequestMapping(value = "download", method = RequestMethod.GET)
public ResponseEntity testDownload(HttpServletRequest request, @RequestParam String filename) throws Exception {

    String parent = request.getServletContext().getRealPath("/resources");
    File file = new File(parent, filename);

    byte[] body = FileUtils.readFileToByteArray(file);

    String downloadFilename = new String(file.getName().getBytes("utf-8"), "iso-8859-1");

    HttpHeaders headers = new HttpHeaders();
    //設置文件類型
    headers.add("Content-Disposition", "attchement;filename=" + downloadFilename);

    ResponseEntity responseEntity = new ResponseEntity(body, headers, HttpStatus.OK);
    return responseEntity;
}
十四、攔截器

SpringMVC的處理器攔截器,類似于 Servlet 開發(fā)中的過濾器 Filter,用于對處理器進行預處理和后處理。

1.過濾器與攔截器區(qū)別

過濾器:依賴于servlet容器,在實現(xiàn)上基于函數(shù)回調(diào),可以對幾乎所有請求進行過濾,但是缺點是一個過濾器實例只能在容器初始化時調(diào)用一次。使用過濾器的目的是用來做一些過濾操作,比如:在過濾器中修改字符編碼;在過濾器中修改HttpServletRequest的一些參數(shù),包括:過濾低俗文字、危險字符等。

攔截器:依賴于web框架,在實現(xiàn)上基于Java的反射機制,屬于面向切面編程(AOP)的一種運用。由于攔截器是基于web框架的調(diào)用,因此可以使用Spring的依賴注入(DI)進行一些業(yè)務操作,同時一個攔截器實例在一個 Controller 生命周期之內(nèi)可以多次調(diào)用。

2.攔截器接口

攔截器一個有3個回調(diào)方法,而一般的過濾器Filter才兩個:

preHandle預處理回調(diào)方法,實現(xiàn)處理器的預處理。返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);false表示流程中斷,不會繼續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過 response 來產(chǎn)生響應;

postHandle后處理回調(diào)方法,實現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過 modelAndView(模型和視圖對象)對模型數(shù)據(jù)進行處理或?qū)σ晥D進行處理。

afterCompletion整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進行一些資源清理,類似于 try-catch-finally 中的finally

3.代碼編寫

有時候我們可能只需要實現(xiàn)三個回調(diào)方法中的某一個,如果實現(xiàn)HandlerInterceptor 接口的話,三個方法必須實現(xiàn),此時 SpringMVC 提供了一個 HandlerInterceptorAdapter 適配器(一種適配器設計模式的實現(xiàn)),允許我們只實現(xiàn)需要的回調(diào)方法,該適配器內(nèi)部實現(xiàn)了 HandlerInterceptor 接口。

先寫兩個攔截器

public class HandlerInterceptor1 extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("HandlerInterceptor1 preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1 postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("HandlerInterceptor1 afterCompletion");
    }
}
public class HandlerInterceptor2 extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("HandlerInterceptor2 preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor2 postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("HandlerInterceptor2 afterCompletion");
    }
}

攔截器的注入


    
    

Controller 方法編寫

@RequestMapping(value = "/hello")
public String testHello() {
    System.out.println("HelloController.testHello");
    return "success";
}

最終輸出看下執(zhí)行順序

HandlerInterceptor1 preHandle
HandlerInterceptor2 preHandle
HelloController.testHello
HandlerInterceptor2 postHandle
HandlerInterceptor1 postHandle
HandlerInterceptor2 afterCompletion
HandlerInterceptor1 afterCompletion
4.運行流程圖

5.選擇性攔截注入

有的時候我們需要攔截器攔截指定的請求,這樣也是可以配置的


    
        
        
        
        
        
    

    
        
        
        
    
十五、異常處理

在SpringMVC中,所有用于處理在請求映射和請求處理過程中拋出的異常的類,都要實現(xiàn) HandlerExceptionResolver 接口。
一個基于SpringMVC的Web應用程序中,可以存在多個實現(xiàn)了 HandlerExceptionResolver 的異常處理類,他們的執(zhí)行順序是由其 order 的值從小到大來先后執(zhí)行,直到遇到返回的 ModelAndView 不為空則終斷接下來的異常解析器的執(zhí)行并返回異常的 ModelAndView 對象。

標簽會幫我們注入常用的三個異常解析器:ExceptionHandlerExceptionResolverResponseStatusExceptionResolverDefaultHandlerExceptionResolver

但是我們接下來重點是了解下常用的兩個異常解析器,分別是:ExceptionHandlerExceptionResolverSimpleMappingExceptionResolver

1.ExceptionHandlerExceptionResolver

注意 @ExceptionHandler 注解修飾的方法里面,只能自己 newModelAndView 對象然后裝入需要的注入的值,對于傳參里面帶的 ModelModelMap 達不到傳值要求。

① 異常處理方法寫在對應的類里面

這樣只能處理該 Controller 里面的異常

處理該 Controller 里面所有的異常,在沒有找到指定的異常類對應的處理方法的前提下

@ExceptionHandler
public ModelAndView handlerAllException(Exception e) {
    ModelAndView mv = new ModelAndView();
    mv.addObject("exceptionMsg", e.getMessage());
    mv.setViewName("error");
    System.out.println("HelloController.handlerAllException");
    return mv;
}

處理該 Controller 里面指定類型的異常

@ExceptionHandler(value = {ArithmeticException.class})
public ModelAndView handlerArithmeticException(Exception e) {
    ModelAndView mv = new ModelAndView();
    mv.addObject("exceptionMsg", e.getMessage());
    mv.setViewName("error");
    System.out.println("HelloController.handlerArithmeticException");
    return mv;
}
② 異常處理方法寫在多帶帶的異常處理類里面

這樣可以處理所有 Controller 的異常,而不是針對單個的 Controller 類,類上需要用 @ControllerAdvice 注解修飾。

@ControllerAdvice
public class HandlerException {
    @ExceptionHandler
    public ModelAndView handlerAllException(Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("exceptionMsg", e.getMessage());
        mv.setViewName("error");
        System.out.println("HelloController.handlerAllException");
        return mv;
    }
    @ExceptionHandler(value = {ArithmeticException.class})
    public ModelAndView handlerArithmeticException(Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("exceptionMsg", e.getMessage());
        mv.setViewName("error");
        System.out.println("HelloController.handlerArithmeticException");
        return mv;
    }
}
2.SimpleMappingExceptionResolver

不用自己寫java類處理異常,直接配置就可以了


    
    
    
        
            error
        
    
十六、整合SpringIOC和SpringMVC

在 web.xml 中配置 contextLoaderListener,并且加入spring的配置文件 applicationContext.xml

這樣可以把 service、dao、事務、緩存、以及和其它框架的整合放到 spring 的配置文件里面
web.xml 文件配置如下





    
    
        contextConfigLocation
        classpath:applicationContext.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    
    
    
    
        dispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring-mvc.xml
        
        1
    

    
        dispatcherServlet
        /
    

在 web.xml 中配置 SpringMVC 的 Servlet 和加入 springmvc.xml,這時兩個配置文件中掃描的包有重合的時候出現(xiàn)某些bean會被初始化2次的問題。

解決:在掃描包的子節(jié)點下配置 exclude-filterinclude-filter

SpringMVC 只掃描 @Controller@ControllerAdvice


    
    

Spring排除掃描 @Controller@ControllerAdvice


    
    

注意:Spring 和 SpringMVC 都有一個 IOC 容器,并且Controller 類的 bean 在 SpringMVC 的 IOC 容器中,但是它可以引用 Spring 的 IOC 容器中的 bean 如 service 和 dao 層的 bean,反之則不行,因為 Spring IOC 容器和 SpringMVC IOC 容器是父子關系,相當于全局變量和局部變量的關系!

十七、SpringMVC運行流程

其他相關文章

SpringMVC入門筆記
SpringMVC工作原理之處理映射HandlerMapping
SpringMVC工作原理之適配器HandlerAdapter
SpringMVC工作原理之參數(shù)解析
SpringMVC之自定義參數(shù)解析
SpringMVC工作原理之視圖解析及自定義
SpingMVC之標簽

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73032.html

相關文章

  • SpringMVC入門筆記

    摘要:入門筆記簡介是一種基于的實現(xiàn)了設計模式的請求驅(qū)動類型的輕量級框架,是系開源項目中的一個,和配合使用。配置在中需要添加使用的和映射規(guī)則。入門較快,而掌握起來相對較難。 SpringMVC入門筆記 1. 簡介 Spring MVC是一種基于Java的實現(xiàn)了Web MVC設計模式的請求驅(qū)動類型的輕量級Web框架 ,是Spring系開源項目中的一個,和IoC配合使用。通過策略接口,Spring...

    zhaochunqi 評論0 收藏0
  • Java學習路線總結(jié),搬磚工逆襲Java架構師(全網(wǎng)最強)

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號作者架構師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

    Scorpion 評論0 收藏0
  • SpringMVC入門就這么簡單

    摘要:也就是說映射器就是用于處理什么樣的請求提交給處理。這和是一樣的提交參數(shù)的用戶名編號提交配置處理請求注冊映射器包框架接收參數(shù)設置無參構造器,里邊調(diào)用方法,傳入要封裝的對象這里的對象就表示已經(jīng)封裝好的了對象了。 什么是SpringMVC? SpringMVC是Spring家族的一員,Spring是將現(xiàn)在開發(fā)中流行的組件進行組合而成的一個框架!它用在基于MVC的表現(xiàn)層開發(fā),類似于struts...

    SKYZACK 評論0 收藏0
  • 慕課網(wǎng)_《SpringMVC數(shù)據(jù)綁定入門》學習總結(jié)

    摘要:數(shù)據(jù)綁定入門學習總結(jié)時間年月日星期日說明本文部分內(nèi)容均來自慕課網(wǎng)。慕課網(wǎng)教學示例源碼個人學習源碼第一章課程介紹數(shù)據(jù)綁定入門概述數(shù)據(jù)綁定概念來自百度百科簡單綁定是將一個用戶界面元素控件的屬性綁定到一個類型對象實例上的某個屬性的方法。 《SpringMVC數(shù)據(jù)綁定入門》學習總結(jié) 時間:2017年2月19日星期日說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.co...

    Karrdy 評論0 收藏0
  • angularjs+springMvc學習筆記

    摘要:回調(diào)說白了,就是把函數(shù)當參數(shù)傳給另一根函數(shù),在另一個函數(shù)執(zhí)行時調(diào)用此函數(shù)例如,在下面這段代碼中,上面定義了兩個函數(shù)和,下面的方法請求成功執(zhí)行,失敗執(zhí)行異步異步的原理我看了網(wǎng)上的一些博客和例子,大都以定時任務為例子說明,但具體的原理我還是不太 回調(diào) 說白了,就是把函數(shù)當參數(shù)傳給另一根函數(shù),在另一個函數(shù)執(zhí)行時調(diào)用此函數(shù)例如,在下面這段代碼中,上面定義了兩個函數(shù)success和error,下...

    dreamGong 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<