springmvc

加載順序

根據(jù)Servlet規(guī)范棠隐,各組件的加載 順序如下:

順序就是:context-param -> listener -> filter -> servlet

對(duì)于某類配置節(jié)而言涝动,與它們出現(xiàn)的順序是有關(guān)的辽社。

以 filter 為例,web.xml 中當(dāng)然可以定義多個(gè) filter耗绿,與 filter 相關(guān)的一個(gè)配置節(jié)是 filter-mapping得运,這里一定要注意,對(duì)于擁有相同 filter-name 的 filter 和 filter-mapping 配置節(jié)而言棒呛,filter-mapping 必須出現(xiàn)在 filter 之后,否則當(dāng)解析到 filter-mapping 時(shí)域携,它所對(duì)應(yīng)的 filter-name 還未定義。web Tomcat啟動(dòng)時(shí)初始化每個(gè) filter 時(shí)鱼喉,是按照 filter 配置節(jié)出現(xiàn)的順序來(lái)初始化的秀鞭,當(dāng)請(qǐng)求資源匹配多個(gè) filter-mapping 時(shí)趋观,filter 攔截資源是按照 filter-mapping 配置節(jié)出現(xiàn)的順序來(lái)依次調(diào)用 doFilter() 方法的。

Servlet的mapping 同 filter 類似锋边。

關(guān)于Servlet的load-on-startup:

load-on-startup 元素在web應(yīng)用啟動(dòng)的時(shí)候指定了servlet被加載的順序皱坛,它的值必須是一個(gè)整數(shù)。如果它的值是一個(gè)負(fù)整數(shù)或是這個(gè)元素不存在豆巨,那么Tomcat會(huì)在該servlet被調(diào)用的時(shí)候剩辟,加載這個(gè)servlet 。如果值是正整數(shù)或零往扔,Tomcat在加載配置的時(shí)候就加載并初始化這個(gè)servlet贩猎,Tomcat必須保證值小的先被加載。如果值相等萍膛,Tomcat可以自動(dòng)選擇先加載誰(shuí)吭服。

在servlet的配置當(dāng)中,<load-on-startup>0</load-on-startup>的含義是:

            (1)標(biāo)記Tomcat是否在啟動(dòng)的時(shí)候就加載這個(gè)servlet蝗罗。
            (2)當(dāng)值為0或者大于0時(shí)艇棕,表示Tomcat在應(yīng)用啟動(dòng)時(shí)就加載這個(gè)servlet;
            (3)當(dāng)是一個(gè)負(fù)數(shù)時(shí)或者沒(méi)有指定時(shí)串塑,則指示Tomcat在該servlet被選擇時(shí)才加載沼琉。
            (4)正數(shù)的值越小,啟動(dòng)該servlet的優(yōu)先級(jí)越高桩匪。

web.xml中 listener打瘪、filter、servlet等 加載順序

springmvc的listener吸祟、 filter瑟慈、servlet 加載順序及其詳解

https://github.com/seaswalker/spring-analysis/blob/master/note/spring-mvc.md#%E5%88%9D%E5%A7%8B%E5%8C%96

配置文件

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <!-- 如果不設(shè)置init-param標(biāo)簽,則必須在/WEB-INF/下創(chuàng)建xxx-servlet.xml文件屋匕,其中xxx是servlet-name中配置的名稱葛碧。 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/springmvc-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

SpringMVC 工作原理(重要)

簡(jiǎn)單來(lái)說(shuō):

客戶端發(fā)送請(qǐng)求-> 前端控制器 DispatcherServlet 接受客戶端請(qǐng)求 -> 找到處理器映射 HandlerMapping 解析請(qǐng)求對(duì)應(yīng)的 Handler-> HandlerAdapter 會(huì)根據(jù) Handler 來(lái)調(diào)用真正的處理器開(kāi)處理請(qǐng)求,并處理相應(yīng)的業(yè)務(wù)邏輯 -> 處理器返回一個(gè)模型視圖 ModelAndView -> 視圖解析器進(jìn)行解析 -> 返回一個(gè)視圖對(duì)象->前端控制器 DispatcherServlet 渲染數(shù)據(jù)(Moder)->將得到視圖對(duì)象返回給用戶

如下圖所示:

SpringMVC運(yùn)行原理

異常

  1. 異常處理方式一. @ExceptionHandler
  2. 異常處理方式二. 實(shí)現(xiàn)HandlerExceptionResolver接口
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
 
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("發(fā)生全局異常!");
        ModelMap mmp=new ModelMap();
        mmp.addAttribute("ex",ex.getMessage());
        response.addHeader("Content-Type","application/json;charset=UTF-8");
        try {
            new ObjectMapper().writeValue(response.getWriter(),ex.getMessage());
            response.getWriter().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ModelAndView();
    }
 
}
  1. 異常處理方式三. @ControllerAdvice+@ExceptionHandler
  2. 三種方式比較說(shuō)明(強(qiáng)烈推薦各位看一下过吻,我覺(jué)得自己總結(jié)的比較多进泼,嘿嘿,不對(duì)之處請(qǐng)指出纤虽,點(diǎn)我快速前往!)

https://www.cnblogs.com/lvbinbin2yujie/p/10574812.html

HandlerInterceptor

攔截器乳绕,用來(lái)干嘛呢,就比如你需要檢測(cè)用戶的權(quán)限逼纸,或者把請(qǐng)求信息記錄到日志等等洋措,也就是說(shuō)需要在用戶請(qǐng)求前后執(zhí)行的一些行為
首先在 Spring MVC 中是有兩種機(jī)制,第一種就是實(shí)現(xiàn) HandlerInterceptor接口杰刽,還有一種就是實(shí)現(xiàn) Spring 的 WebRequestInterceptor 接口

數(shù)據(jù)綁定和參數(shù)綁定

https://www.cnblogs.com/linjiaxin/p/7753374.html
https://zhuanlan.zhihu.com/p/139162484
http://www.reibang.com/p/bf1ff5b31918

在spring早期版本使用PropertyEditor(只能轉(zhuǎn)java對(duì)象)菠发,后期使用converter(可轉(zhuǎn)換任意類型)

 public class User {
     private String id;
     private String name;
     ......補(bǔ)充其 get set toString 方法
 }
http://localhost:8080/objectType.do?id=001&name=Steven

 public class UserDetails {
     private Integer age;
     private String address;
     ......補(bǔ)充其 get set toString 方法
 }
 public class User {
     private String id;
     private String name;
     
     private UserDetails userDetails;
     
     ......補(bǔ)充其 get set toString 方法
 }
http://localhost:8080/objectType.do?id=1&name=Steven&userDetails.age=20&userDetails.address=BeiJing

對(duì)于引入的對(duì)象成員復(fù)賦值王滤,格式就例如:userDetails.address=xxxxx
這里地址我沒(méi)用中文,是因?yàn)槲沂侵苯臃祷氐淖茵瑳](méi)經(jīng)過(guò)編碼的處理雁乡,不然會(huì)顯示 ? ?

同屬性對(duì)象參數(shù)綁定

如果我們想要直接接收兩個(gè)對(duì)象,有時(shí)候免不了有相同的成員糜俗,例如我們的 User 和 Student 類中均含有

Integer id 踱稍、String name 兩個(gè)成員,我們?cè)囍?qǐng)求一下

http://localhost:8080/objectType2.do?id=8&name=Steven

 @RequestMapping("objectType2.do")
 @ResponseBody
 public String objectType2(User user, Student student) {
     return user.toString() + " " + student.toString();
 }

返回結(jié)果:User{id='8', name='Steven'} Student{id='8', name='Steven'}

可以看到悠抹,兩個(gè)對(duì)象的值都被賦上了珠月,但是,大部分情況下锌钮,不同的對(duì)象的值一般都是不同的桥温,為此,我們還有解決辦法

@InitBinder 注解可以幫助我們分開(kāi)綁定梁丘,下面的代碼也就是說(shuō)分別給 user侵浸、student 指定一個(gè)前綴

http://localhost:8080/objectType2.do?user.id=1&name=Steven&stu.id=002

@InitBinder("user")
 public void initUser(WebDataBinder binder) {
     binder.setFieldDefaultPrefix("user.");
 }
 ?
 @InitBinder("student")
 public void initStudent(WebDataBinder binder) {
     binder.setFieldDefaultPrefix("stu.");
 }

當(dāng)發(fā)起這樣一個(gè)請(qǐng)求后,我們分別指定了 user 和 student 的 id 值氛谜,而 name 則是同樣的 Steven
返回結(jié)果:User{id='1', name='Steven', userDetails=null} Student{id='2', name='Steven'}

// http://localhost:8080/springmvc/objecttype3.do?people.name=Tom&user.name=Lucy
// http://localhost:8080/springmvc/objecttype3.do?people.name=Tom
// http://localhost:8080/springmvc/objecttype3.do?name=Tom
@RequestMapping(value = "objecttype3.do")
@ResponseBody
public String objecttype3(People people, User user) {
    return "people=" + people + ",user=" + user;
}

@InitBinder("people")
public void initPeople(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("people.");
}

@InitBinder("user")
public void initUser(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("user.");
}
 /**
     * 解決前端傳遞的日期參數(shù)驗(yàn)證異常
     *
     * @param binder
     * @author hzj
     */
    @InitBinder({"param", "date"})//指定校驗(yàn)參數(shù)
    protected void initBinder(WebDataBinder binder) {
        // binder.setDisallowedFields("name"); // 不綁定name屬性
        binder.registerCustomEditor(String.class, new StringTrimmerEditor());
 
        // 此處使用Spring內(nèi)置的CustomDateEditor
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }


    @ResponseBody
    @GetMapping("/initbinder")
    public String testInitBinder(String param, Date date) {
        return param + ":" + date;
    }
(三) 數(shù)組類型參數(shù)綁定

http://localhost:8080/arrayType.do?nickname=Jack&nickname=Steven&nickname=Tom

 @RequestMapping("arrayType.do")
 @ResponseBody
 public String arrayType(String[] nickname) {
     StringBuilder sb = new StringBuilder();
     for (String s : nickname) {
         sb.append(s).append(", ");
     }
     return sb.toString();
 }

返回結(jié)果:Jack, Steven, Tom,

集合類型參數(shù)綁定List 類型

http://localhost:8080/listType.do?users[0].id=1&users[0].name=Jack&users[1].id=2&users[1].name=Marry

@RequestMapping("listType.do")
 @ResponseBody
 public String listType(UserList userList) {
     return userList.toString();
 }

http://localhost:8080/listType.do?users%5B0%5D.id=1&users%5B0%5D.name=Jack&users%5B1%5D.id=2&users%5B1%5D.name=Marry

Tomcat高的版本地址中不能使用“[”和“]” 掏觉,我們可以將其換成對(duì)應(yīng)的16進(jìn)制,即 “[” 換成 %5B值漫,“]” 換成 %5D
或者直接用 post 請(qǐng)求也是可以的哈

Map 類型

http://localhost:8080/mapType.do?users['userA'].id=1&users['userA'].name=Jack&users['userB'].id=2&users['userB'].name=Tom

public String mapType(UserMap userMap)

json

data:'{"id":"37","name":"張三"}',

public Admin ajaxType1(@RequestBody Admin admin)
public Admin ajaxType3(@RequestBody Map<String, String> map)

https://zhuanlan.zhihu.com/p/139162484

類型轉(zhuǎn)換

springmvc參數(shù)類型轉(zhuǎn)換三種方式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末澳腹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杨何,更是在濱河造成了極大的恐慌酱塔,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件危虱,死亡現(xiàn)場(chǎng)離奇詭異羊娃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)埃跷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門蕊玷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人弥雹,你說(shuō)我怎么就攤上這事垃帅。” “怎么了剪勿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵贸诚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)酱固,這世上最難降的妖魔是什么二鳄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮媒怯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘髓窜。我一直安慰自己扇苞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布寄纵。 她就那樣靜靜地躺著鳖敷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪程拭。 梳的紋絲不亂的頭發(fā)上定踱,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音恃鞋,去河邊找鬼崖媚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恤浪,可吹牛的內(nèi)容都是我干的畅哑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼水由,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荠呐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起砂客,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤泥张,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鞠值,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體媚创,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年齿诉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筝野。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粤剧,死狀恐怖歇竟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抵恋,我是刑警寧澤焕议,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站弧关,受9級(jí)特大地震影響盅安,放射性物質(zhì)發(fā)生泄漏唤锉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一别瞭、第九天 我趴在偏房一處隱蔽的房頂上張望窿祥。 院中可真熱鬧,春花似錦蝙寨、人聲如沸晒衩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)听系。三九已至,卻和暖如春虹菲,著一層夾襖步出監(jiān)牢的瞬間靠胜,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工毕源, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浪漠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓脑豹,卻偏偏與公主長(zhǎng)得像郑藏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘩欺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354