Spring MVC

Spring mvc 介紹

Spring Web MVC是一種基于Java的實(shí)現(xiàn)了Web MVC設(shè)計(jì)模式的請(qǐng)求驅(qū)動(dòng)類(lèi)型的輕量級(jí)Web框架澳眷,即使用了MVC架構(gòu)模式的思想胡嘿,將web層進(jìn)行職責(zé)解耦,基于請(qǐng)求驅(qū)動(dòng)指的就是使用請(qǐng)求-響應(yīng)模型钳踊,框架的目的就是幫助我們簡(jiǎn)化開(kāi)發(fā)衷敌,Spring Web MVC也是要簡(jiǎn)化我們?nèi)粘eb開(kāi)發(fā)


image.png

spring mvc 常用注解詳解

@Controller

在SpringMVC 中,控制器Controller 負(fù)責(zé)處理由DispatcherServlet 分發(fā)的請(qǐng)求拓瞪,它把用戶(hù)請(qǐng)求的數(shù)據(jù)經(jīng)過(guò)業(yè)務(wù)處理層處理之后封裝成一個(gè)Model 缴罗,然后再把該Model 返回給對(duì)應(yīng)的View 進(jìn)行展示。在SpringMVC 中提供了一個(gè)非常簡(jiǎn)便的定義Controller 的方法祭埂,你無(wú)需繼承特定的類(lèi)或?qū)崿F(xiàn)特定的接口面氓,只需使用@Controller 標(biāo)記一個(gè)類(lèi)是Controller ,然后使用@RequestMapping 等一些注解用以定義請(qǐng)求URL 請(qǐng)求和Controller 方法之間的映射蛆橡,這樣的Controller 就能被外界訪問(wèn)到舌界。其標(biāo)記在一個(gè)類(lèi)上,使用它標(biāo)記的類(lèi)就是一個(gè)SpringMVC Controller 對(duì)象泰演。分發(fā)處理器將會(huì)掃描使用了該注解的類(lèi)的方法呻拌,并檢測(cè)該方法是否使用@RequestMapping 注解。@Controller 只是定義了一個(gè)控制器類(lèi)睦焕,而使用@RequestMapping 注解的方法才是真正處理請(qǐng)求的處理器柏锄。此外我們還需要將controller注冊(cè)到spring里

@RequestMapping

RequestMapping是一個(gè)用來(lái)處理請(qǐng)求地址映射的注解,可用于類(lèi)或方法上复亏。用于類(lèi)上趾娃,表示類(lèi)中的所有響應(yīng)請(qǐng)求的方法都是以該地址作為父路徑,作用于方法上缔御,表明該處理器的請(qǐng)求地址=父路徑+方法上url+method抬闷,其擁有6個(gè)屬性

1、 value, method笤成;定義處理器訪問(wèn)的具體體質(zhì)
value: 指定請(qǐng)求的實(shí)際地址评架,指定的地址可以是URI Template 模式;
method: 指定請(qǐng)求的method類(lèi)型炕泳, GET纵诞、POST、PUT培遵、DELETE等浙芙;
2、consumes籽腕,produces 定義處理器內(nèi)容類(lèi)型
consumes: 指定處理請(qǐng)求的提交內(nèi)容類(lèi)型(Content-Type)嗡呼,例如application/json, text/html;
produces: 指定返回的內(nèi)容類(lèi)型,僅當(dāng)request請(qǐng)求頭中的(Accept)類(lèi)型中包含該指定類(lèi)型才返回皇耗;
3南窗、params,headers 定義處理器處理類(lèi)型
params: 指定request中必須包含某些參數(shù)值郎楼,才讓該方法處理万伤!
headers: 指定request中必須包含某些指定的header值,才能讓該方法處理請(qǐng)求呜袁。

@PathVariable

用于將請(qǐng)求URL中的模板變量映射到功能處理方法的參數(shù)上壕翩,即取出uri模板中的變量作為參數(shù)。如:

@Controller  
public class TestController {  
     @RequestMapping(value="/user/{userId}/roles/{roleId}",method = RequestMethod.GET)  
     public String getLogin(@PathVariable("userId") String userId,  
         @PathVariable("roleId") String roleId){  
         System.out.println("取出請(qǐng)求路徑攜帶的參數(shù)->User Id : " + userId);  
         System.out.println("取出請(qǐng)求路徑攜帶的參數(shù)->Role Id : " + roleId);  
         return "hello";  
     }  
}

@requestParam

@requestParam主要用于在SpringMVC后臺(tái)控制層獲取參數(shù)傅寡,類(lèi)似一種是request.getParameter("name")放妈,它有三個(gè)常用參數(shù):defaultValue = "0", required = false, value = "isApp";defaultValue 表示設(shè)置默認(rèn)值荐操,required 銅過(guò)boolean設(shè)置是否是必須要傳入的參數(shù)芜抒,value 值表示接受的傳入的參數(shù)類(lèi)型。

@ResponseBody

作用: 該注解用于將Controller的方法返回的對(duì)象托启,通過(guò)適當(dāng)?shù)腍ttpMessageConverter轉(zhuǎn)換為指定格式后宅倒,寫(xiě)入到Response對(duì)象的body數(shù)據(jù)區(qū)。使用時(shí)機(jī):返回的數(shù)據(jù)不是html標(biāo)簽的頁(yè)面屯耸,而是其他某種格式的數(shù)據(jù)時(shí)(如json等)使用拐迁;

@RequestBody

該注解常用來(lái)處理Content-Type: 不是application/x-www-form-urlencoded編碼的內(nèi)容,例如application/json, application/xml等疗绣;它是通過(guò)使用HandlerAdapter 配置的HttpMessageConverters來(lái)解析post data body线召,然后綁定到相應(yīng)的bean上的。

@RequestMapping(value = "/something", method = RequestMethod.PUT)  
public void handle(@RequestBody String body, Writer writer) throws IOException {  
  writer.write(body);  
} 

spring mvc 攔截器配置

preHandle:預(yù)處理回調(diào)方法多矮,返回值:true表示繼續(xù)流程缓淹,false表示流程中斷(如登錄檢查失敼颉),不會(huì)繼續(xù)續(xù)調(diào)用其他的攔截器或處理器讯壶,此時(shí)我們需要通過(guò)response來(lái)產(chǎn)生響應(yīng)料仗;
postHandle:后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前)伏蚊,此時(shí)我們可以通過(guò)modelAndView(模型和視圖對(duì)象)對(duì)模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理立轧,modelAndView也可能為null。
afterCompletion:整個(gè)請(qǐng)求處理完畢回調(diào)方法躏吊,即在視圖渲染完畢時(shí)回調(diào)氛改,如性能監(jiān)控中我們可以在此記錄結(jié)束時(shí)間并輸出消耗時(shí)間,還可以進(jìn)行一些資源清理颜阐,類(lèi)似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中preHandle返回true的攔截器的afterCompletion吓肋。

public class Login implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest httpRequest,
            HttpServletResponse httpResponse, Object arg2, Exception arg3)
            throws Exception {
         
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object object) throws Exception {
        /*HttpServletRequest httpRequest = (HttpServletRequest) request;  
         HttpServletResponse httpResponse = (HttpServletResponse) response;*/
        String urlString = request.getRequestURI();
            
        ///olForum/forumList.html模擬登錄頁(yè)
        if(urlString.endsWith("forumList.html")){
            return true;
        }
        //請(qǐng)求的路徑
        String contextPath=request.getContextPath();
       
        /*httpRequest.getRequestDispatcher("/olForum/forumList").forward(httpRequest, httpResponse);*/
        /*response.sendRedirect(contextPath+"/olForum/forumList.html");*/
        response.sendRedirect(contextPath + "/olForum/forumList.html?login=aaa");  
        return false;
        /*httpResponse.sendRedirect(httpRequest.getContextPath()+"/olForum/forumList.html");
        return;*/
       
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 掃描controller(controller層注入) -->
    <context:component-scan base-package="com.bybo.aca.web.controller"/>
  
<mvc:interceptors>  
   <!--  使用bean定義一個(gè)Interceptor凳怨,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請(qǐng)求   -->
    <!-- <bean class="com.bybo.aca.web.interceptor.Login"/> -->   
    <mvc:interceptor>  
        <!-- 進(jìn)行攔截:/**表示攔截所有controller -->
        <mvc:mapping path="/**" />
       <!-- 不進(jìn)行攔截 -->
        <mvc:exclude-mapping path="/index.html"/>
       
        <bean class="com.bybo.aca.web.interceptor.Login"/>  
    </mvc:interceptor>  
</mvc:interceptors>     
    
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/views/" p:suffix=".jsp"/>
    
</beans>

spring mvc 靜態(tài)資源放問(wèn)配置

image.png
 <!-- 視圖解析器 -->
    <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前綴 -->
        <property name="prefix" value="/WEB-INF/CraCoreHtml/"></property>
        <!-- 后綴 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 解決靜態(tài)資源被攔截的問(wèn)題 -->
    <mvc:default-servlet-handler/>

spring mvc 文件上傳

<!-- SpringMVC上傳文件時(shí),需要配置MultipartResolver處理器 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8" />
        <!-- 指定所上傳文件的總大小,單位字節(jié)是鬼。注意maxUploadSize屬性的限制不是針對(duì)單個(gè)文件肤舞,而是所有文件的容量之和 -->
        <property name="maxUploadSize" value="10240000" />
    </bean>

前端

 <form action="/shop/auth/photoUpload" method="post" enctype="multipart/form-data">
     選擇文件:<input type="file" name="file">
     <input type="submit" value="上傳"> 
 </form>

后端

@RequestMapping(value = "taskUpload", produces = "text/html;charset=UTF-8", method = RequestMethod.POST)
    public ResponseEntity<String> taskUpload(@Validated Task task, HttpServletRequest request) throws Exception {


        if (StringUtils.isNotBlank(task.getAnnouncement())) {
            String type = task.getType();
            return Optional.ofNullable(taskService.saveSelective(task))
                    .filter((value) -> value > 0)
                    .map(result -> new ResponseEntity<>(type + "公告發(fā)布成功", HttpStatus.OK))
                    .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).body("公告發(fā)布失敗"));

        }

        File newFile = null;

        try {
            CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
                    request.getSession().getServletContext());
            if (request instanceof MultipartHttpServletRequest) {
                // 將request變成多部分request
                MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
                Iterator<String> iter = multiRequest.getFileNames();
                // 檢查form中是否有enctype="multipart/form-data"
                if (multipartResolver.isMultipart(request) && iter.hasNext()) {
                    // 獲取multiRequest 中所有的文件名
                    while (iter.hasNext()) {
                        List<MultipartFile> fileRows = multiRequest.getFiles(iter.next().toString());
                        if (fileRows != null && fileRows.size() != 0) {
                            for (MultipartFile file : fileRows) {
                                if (file != null && !file.isEmpty()) {
                                    // 文件新路徑
                                    String filePath = getFilePath(request, file.getOriginalFilename());
                                    newFile = new File(filePath);
                                    // 寫(xiě)文件到磁盤(pán)
                                    file.transferTo(newFile);
                                    String type = task.getType();
                                    if (newFile.exists()) {
                                        CraFile craFile = new CraFile();
                                        craFile.setFilePath(filePath);
                                        craFile.setFileType(task.getType());
                                        Integer integer = fileService.saveSelective(craFile);
                                        if (integer > 0) {
                                            task.setFileId(craFile.getId());
                                            return Optional.ofNullable(taskService.saveSelective(task))
                                                    .filter((value) -> value > 0)
                                                    .map(result -> new ResponseEntity<>(type + "上傳成功", HttpStatus.OK))
                                                    .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗"));
                                        }
                                    } else {
                                        return ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗");
                                    }

                                }else {
                                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("未能檢測(cè)到上傳文件");
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            if (newFile != null) {
                if (newFile.exists()) {
                    newFile.delete();
                }
            }
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗");
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("服務(wù)器繁忙");
    }

spring mvc 工作流程詳解

image.png

1、 用戶(hù)發(fā)送請(qǐng)求至前端控制器DispatcherServlet均蜜。
2李剖、 DispatcherServlet收到請(qǐng)求調(diào)用HandlerMapping處理器映射器。
3囤耳、 處理器映射器找到具體的處理器(可以根據(jù)xml配置篙顺、注解進(jìn)行查找),生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet充择。
4德玫、 DispatcherServlet調(diào)用HandlerAdapter處理器適配器。
5椎麦、 HandlerAdapter經(jīng)過(guò)適配調(diào)用具體的處理器(Controller宰僧,也叫后端控制器)。
6观挎、 Controller執(zhí)行完成返回ModelAndView琴儿。
7、 HandlerAdapter將controller執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet嘁捷。
8造成、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。
9雄嚣、 ViewReslover解析后返回具體View谜疤。
10、DispatcherServlet根據(jù)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)。
11夷磕、 DispatcherServlet響應(yīng)用戶(hù)履肃。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坐桩,隨后出現(xiàn)的幾起案子尺棋,更是在濱河造成了極大的恐慌,老刑警劉巖绵跷,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膘螟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碾局,警方通過(guò)查閱死者的電腦和手機(jī)荆残,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)净当,“玉大人内斯,你說(shuō)我怎么就攤上這事∠裉洌” “怎么了俘闯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)忽冻。 經(jīng)常有香客問(wèn)我真朗,道長(zhǎng),這世上最難降的妖魔是什么僧诚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任遮婶,我火速辦了婚禮,結(jié)果婚禮上湖笨,老公的妹妹穿的比我還像新娘蹭睡。我一直安慰自己,他們只是感情好赶么,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布肩豁。 她就那樣靜靜地躺著,像睡著了一般辫呻。 火紅的嫁衣襯著肌膚如雪清钥。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天放闺,我揣著相機(jī)與錄音祟昭,去河邊找鬼。 笑死怖侦,一個(gè)胖子當(dāng)著我的面吹牛篡悟,可吹牛的內(nèi)容都是我干的谜叹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼搬葬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荷腊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起急凰,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤女仰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后抡锈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體疾忍,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年床三,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了一罩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撇簿,死狀恐怖聂渊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情补疑,我是刑警寧澤歧沪,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布歹撒,位于F島的核電站莲组,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏暖夭。R本人自食惡果不足惜锹杈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望迈着。 院中可真熱鬧竭望,春花似錦、人聲如沸裕菠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奴潘。三九已至旧烧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間画髓,已是汗流浹背掘剪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奈虾,地道東北人夺谁。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓廉赔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親匾鸥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜡塌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容