第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
2.3 綁定數(shù)據(jù)

使用 @RequestParam 注解Spring MVC 提供有 @RequestParam 注解,通過(guò)給定參數(shù)名,可以自動(dòng)綁定請(qǐng)求包中的同名參數(shù)的數(shù)據(jù)。代碼如下:@Controller@RequestMapping("/user")public class UserAction { @RequestMapping("/register") public String register(@RequestParam("userName") String userNmae, @RequestParam("userPassword") String userPassword) { System.out.println(userNmae); System.out.println(userPassword); return null; }}此處,使用 @RequestParam 注解綁定請(qǐng)求包中的數(shù)據(jù),有 2 個(gè)弊端:如果請(qǐng)求包中傳過(guò)來(lái)的數(shù)據(jù)較多,控制器中響應(yīng)方法的參數(shù)也會(huì)增多,代碼臃腫不好維護(hù);Java 語(yǔ)言最大的特色是面向?qū)ο缶幊蹋∣OP)。很顯然,userName 和 userPassword 都是用戶的信息,以一種拆離的方式分別注入數(shù)據(jù)沒(méi)有體現(xiàn)出 OOP 的優(yōu)點(diǎn)。那么,有沒(méi)有一種更好的替代方案或者說(shuō)有一種很 OOP 的方案呢?以 OOP 方式綁定數(shù)據(jù)從 OOP 的角度分析,在應(yīng)用程序中必然會(huì)存在一個(gè)描述用戶的類。public class User { private String userName; private String userPassword; //……}能不能直接把請(qǐng)求包中提交的數(shù)據(jù)綁定到 User 類型中?答案是肯定的,而且實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,只需要把控制器方法的參數(shù)修改成對(duì)象類型便可。@RequestMapping("/register",method = RequestMethod.POST)public String register(User user) { System.out.println(user); return null;}不需要使用額外的任何注解,就可以直接綁定表單中的數(shù)據(jù)。為什么表單中的數(shù)據(jù)能自動(dòng)綁定到對(duì)象上?原理很簡(jiǎn)單,表單中數(shù)據(jù)以 key=value&key=value 的方式提交,此處的 key 實(shí)質(zhì)是表單控件的名稱。前面的注冊(cè)表單中的數(shù)據(jù)在請(qǐng)求包中的格式形式如下:userNname=abc&userPassword=123456如上圖所示,Spring MVC 能自動(dòng)解析這個(gè)數(shù)據(jù),然后自動(dòng)注入到對(duì)象的同名屬性中。所以一定要保證對(duì)象的屬性名與表單中提交數(shù)據(jù)時(shí)使用的參數(shù)名(key)一致。數(shù)據(jù)解析成功后,理論上講應(yīng)該要把數(shù)據(jù)送到數(shù)據(jù)庫(kù)中,本章節(jié)暫不涉及到數(shù)據(jù)庫(kù)操作。只做業(yè)務(wù)邏輯模擬。@RequestMapping(value="/register",method = RequestMethod.POST)public String register(User user) { if("abc".equals(user.getUserName()) && "123456".equals(user.getUserPassword()) ) { return "success"; }else { return "fail"; } }

3. 模板方式

Spring MVC 提供有一種所謂的模板方法,和前面的以查詢字符串方法進(jìn)行附加沒(méi)有多大區(qū)別。如下面的代碼,數(shù)據(jù)模型中的 data 對(duì)應(yīng)數(shù)據(jù)會(huì)以 URL 變量方式傳遞。數(shù)據(jù)模型中其它數(shù)據(jù)則以查詢字符串方式進(jìn)行傳遞。@RequestMapping("/response04") public String response04(ModelMap model) throws IOException { // 發(fā)送給客戶端的響應(yīng)數(shù)據(jù) String hello = "Hello"; model.addAttribute("data", hello); model.addAttribute("id", 1); return "redirect:/test/{data}"; } ? @RequestMapping("/test/{data}") public String response05(@PathVariable("data") String data,@RequestParam("id") int id) throws IOException { System.out.println(data); System.out.println(id); return null; }當(dāng)在瀏覽器中請(qǐng)求 http://localhost:8888/sm-demo/response04 后,瀏覽器的地址欄中會(huì)變成 :http://localhost:8888/sm-demo/test/Hello?id=1。模板方式其本質(zhì)和查詢字符串沒(méi)有太多區(qū)別。

Android 列表控件 ListView

在學(xué)習(xí)了 ScrollView 及 Adapter 兩節(jié)內(nèi)容之后,大家應(yīng)該對(duì) ListView 有了一些基本的了解,它是一個(gè)列表樣式的 ViewGroup,將若干 item 按行排列。ListView 是一個(gè)很基本的控件也是 Android 中最重要的控件之一。它可以幫助我們完成多個(gè) View 的垂直排列并支持滾動(dòng)顯示效果,而它比 ScrollView 更靈活也更易擴(kuò)展,Adapter 作為 UI 控件和數(shù)據(jù)源之間的橋梁,會(huì)幫我們實(shí)現(xiàn) MVC 模式,所以在實(shí)際開(kāi)發(fā)中大多數(shù)的列表場(chǎng)景我們會(huì)優(yōu)先考慮使用 ListView 來(lái)實(shí)現(xiàn)(目前 Google 推出了新的更強(qiáng)大的列表控件——RecyclerView,不過(guò)基本原理和 ListView 類似)。

2. 請(qǐng)求作用域

WEB 程序的應(yīng)用層使用的是 HTTP 協(xié)議,HTTP 協(xié)議有一個(gè)特點(diǎn),無(wú)狀態(tài)。所謂無(wú)狀態(tài)指上一次請(qǐng)求與下一次請(qǐng)求之間是隔離的,沒(méi)有內(nèi)在的聯(lián)系。更通俗的講,可理解為一個(gè)患有健忘癥的人,只記得當(dāng)前自己在做什么,不記得自己曾經(jīng)做過(guò)什么,更不會(huì)知道自己將來(lái)要做什么。HTTP 協(xié)議的這種無(wú)狀態(tài),最初設(shè)計(jì)時(shí)是從安全角度考慮。但是,在某些應(yīng)用場(chǎng)景下,如購(gòu)物車的應(yīng)用場(chǎng)景下,卻顯得無(wú)能為力。購(gòu)物車中的商品不一定是一次請(qǐng)求下的結(jié)果,往往是多次請(qǐng)求下的結(jié)果。也就是說(shuō),購(gòu)物車需要保存每一次請(qǐng)求獲取到的數(shù)據(jù)。顯然,直接使用 HTTP 協(xié)議是無(wú)法做到的。就需從技術(shù)層面上提供解決方案。原生 Servlet 提供了 3 個(gè)作用域,可以根據(jù)用戶的需要來(lái)保存每一次請(qǐng)求過(guò)程中產(chǎn)生的數(shù)據(jù)。請(qǐng)求作用域: 使用 HttpServletRequest 組件存儲(chǔ)的數(shù)據(jù)可以在每一次的請(qǐng)求周期內(nèi)存在。 請(qǐng)求結(jié)束,數(shù)據(jù)也將消失;會(huì)話作用域: 使用 HttpSession 組件保存的數(shù)據(jù)能在整個(gè)會(huì)話生命周期內(nèi)存在。如購(gòu)物車就可以保存在會(huì)話作用域中;應(yīng)用程序作用域: 使用 ServletContext 組件保存的數(shù)據(jù)在整個(gè)應(yīng)用程序生命周期之內(nèi)存在。Spring MVC 中,把數(shù)據(jù)保存在請(qǐng)求作用域,或是說(shuō)在整個(gè)請(qǐng)求過(guò)程中數(shù)據(jù)都有效。有 2 種解決方案直接使用 HttpServletRequest 組件;使用 Spriing MVC 提供的高級(jí)數(shù)據(jù)模型組件。

3.2 添加依賴包

項(xiàng)目創(chuàng)建成功后,會(huì)發(fā)現(xiàn)項(xiàng)目上有紅色的錯(cuò)誤提示,這個(gè)不用緊張。因?yàn)轫?xiàng)目自動(dòng)創(chuàng)建了一個(gè) jsp 文件,而 jsp 所依賴的 servlet 包我們還沒(méi)有加進(jìn)來(lái)。打開(kāi)項(xiàng)目中的 pom.xml 文件,在文件中添加項(xiàng)目所需要的依賴 jar 包:javax.servlet-api: servlet 規(guī)范包;spring-context: spring 最基礎(chǔ)、最重要的核心包。Maven 有一個(gè)依賴傳遞功能,會(huì)自動(dòng)添加 spring-context 所依賴的其它包;spring-web: spring 對(duì) web 項(xiàng)目的支持包,這個(gè)不用解釋,肯定不能少;spring-webmvc: 從名字上看,知道它應(yīng)該是主角,Spring MVC 核心包。完整的依賴信息如下:<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.13.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.13.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.13.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency></dependencies>Maven 會(huì)自動(dòng)從遠(yuǎn)程倉(cāng)庫(kù)下載這些依賴包,項(xiàng)目中也可以看到下載下來(lái)的依賴包:大家會(huì)看到,除了在 pom.xml 文件中指定的依賴包外,還有其它的包,這個(gè)就是 Maven 的依賴傳遞功能實(shí)現(xiàn)的。好了! 有了這些包后,就可以使用 Spring 提供的 WEB MVC API 了。

1. 前言

WEB 應(yīng)用程序的交互模式通過(guò)請(qǐng)求包與響應(yīng)包來(lái)完成,請(qǐng)求包一般由瀏覽器構(gòu)建,并發(fā)送給服務(wù)器端。服務(wù)器端解析請(qǐng)求包,并根據(jù)具體的業(yè)務(wù)邏輯處理請(qǐng)求包中的數(shù)據(jù),并構(gòu)建響應(yīng)包回應(yīng)請(qǐng)求方。響應(yīng)包的實(shí)體部分中的內(nèi)容可以由控制器的方法決定,或者說(shuō)由需求來(lái)決定。根據(jù)響應(yīng)包中的內(nèi)容不同,可以分兩者響應(yīng)方式:轉(zhuǎn)發(fā):響應(yīng)包直接包含響應(yīng)給瀏覽器的數(shù)據(jù);重定向:響應(yīng)包僅包含數(shù)據(jù)視圖的地址。本節(jié)課程將向大家講解 Spring MVC 中如何實(shí)現(xiàn)轉(zhuǎn)發(fā)和重定向。本章節(jié)的重點(diǎn)是了解轉(zhuǎn)發(fā)和重定向的本質(zhì)。

1. Django 框架特點(diǎn)

Django定義了服務(wù)發(fā)布、路由映射、模板編程、數(shù)據(jù)處理的一整套功能。這也意味著Django模塊之間緊密耦合,開(kāi)發(fā)者需要學(xué)習(xí)Django自己定義的這一整套技術(shù)。Django是遵循MVC架構(gòu)的Web開(kāi)發(fā)框架,其主要由以下幾部分組成。管理工具(Management):一套內(nèi)置的創(chuàng)建站點(diǎn)、遷移數(shù)據(jù)、維護(hù)靜態(tài)文件的命令工具;模型(Model):提供數(shù)據(jù)訪問(wèn)接口和模塊,包括數(shù)據(jù)字段、元數(shù)據(jù)、數(shù)據(jù)關(guān)系等的定義及操作;視圖(View):Django 的視圖層封裝了 HTTP Reques t和 Response 的一系列操作和數(shù)據(jù)流,其主要功能包括URL映射機(jī)制、綁定模板等;模板(Template):是一套 Django 自己的頁(yè)面渲染模板語(yǔ)言,用若干內(nèi)置的 tags 和 filters 定義頁(yè)面的生成方式;表單(Form):通過(guò)內(nèi)置的數(shù)據(jù)類型和控件生成 HTML 表單;管理站(Admin):通過(guò)聲明需要管理的 Model,快速生成后臺(tái)數(shù)據(jù)管理網(wǎng)站。

2. 查詢字符串

如果是轉(zhuǎn)發(fā),數(shù)據(jù)模型只需要是請(qǐng)求作用域級(jí)別的,視圖解析器便能從數(shù)據(jù)模型中拿到所需要的數(shù)據(jù)。對(duì)于重定向,因?yàn)榭缌苏?qǐng)求,視圖無(wú)法讀出請(qǐng)求作用域級(jí)別的數(shù)據(jù)模型中的數(shù)據(jù)。如果要讓數(shù)據(jù)模型中的數(shù)據(jù)被視圖識(shí)別出來(lái),則需要提升數(shù)據(jù)模型的作用域,如升級(jí)為會(huì)話作用域級(jí)別。所謂會(huì)話作用域,意味著數(shù)據(jù)會(huì)存放在服務(wù)器的會(huì)話緩存區(qū)。如果數(shù)據(jù)使用的頻率不是很高,會(huì)產(chǎn)生空間上的浪費(fèi)。有沒(méi)有一種較佳的方案,即不浪費(fèi)服務(wù)器空間,又能傳遞數(shù)據(jù)了?答案是肯定的。最原始的方式便是采用查詢字符串的方式。如下面的實(shí)例:@RequestMapping("/response03") public String response03(ModelMap model) throws IOException { // 發(fā)送給客戶端的響應(yīng)數(shù)據(jù) String hello = "Hello"; model.addAttribute("data", hello); return "redirect:/hello.jsp"; }model 中的數(shù)據(jù)只是請(qǐng)求作用域級(jí)別,重定向后的 hello.jsp 中無(wú)法獲取此數(shù)據(jù), Spring MVC 內(nèi)部處理方式是把數(shù)據(jù)附加在 hello.jsp 后面。打開(kāi)瀏覽器,輸入請(qǐng)求 http://localhost:8888/sm-demo/response03 地址,查看瀏覽器的地址欄中的 URL 變成 http://localhost:8888/sm-demo/hello.jsp?data=Hello。Tips:數(shù)據(jù)附加在 URL 后面是 Spring MVC 自動(dòng)完成的。把 hello.jsp 頁(yè)面中的數(shù)據(jù)讀取方式改成下面的方式(從查詢參數(shù)中讀取)。<div style="color:red">${param.data} </div> 這種方式有 2 個(gè)缺點(diǎn):安全性低,數(shù)據(jù)赤裸裸地暴露在地址欄中;如果數(shù)據(jù)量多,則整個(gè) URL 變得臃腫不易維護(hù)。多數(shù)據(jù)實(shí)例:@RequestMapping("/response03") public String response03(ModelMap model) throws IOException { // 發(fā)送給客戶端的響應(yīng)數(shù)據(jù) String hello = "Hello"; model.addAttribute("data", hello); model.addAttribute("id", 1); return "redirect:/hello.jsp"; }當(dāng)請(qǐng)求后,URL 會(huì)變成 http://localhost:8888/sm-demo/hello.jsp?data=Hello&id=1 。

3.3. 靜態(tài)資源

如果瀏覽器中請(qǐng)求的是一個(gè)靜態(tài)資源(瀏覽器能解釋的資源,如 Html、Css、Js、圖片……),有必要經(jīng)過(guò)前端控制器嗎?當(dāng)然不需要。但是,你可以試著在 WEB 項(xiàng)目的 根目錄下創(chuàng)建名為 static.html 的靜態(tài)資源,然后在瀏覽器直接請(qǐng)求一下(http://localhost:8888/sm-demo/static.html)。會(huì)發(fā)現(xiàn)請(qǐng)求不到,那是因?yàn)槟愕恼?qǐng)求還是經(jīng)過(guò)了前端控制器。所以,咱們要告訴 Spring MVC 靜態(tài)資源還是交回給 Servlet 容器處理吧, 就不勞您大駕了。打開(kāi) WebConfig 配置類,讓其實(shí)現(xiàn) WebMvcConfigurer 接口;public class WebConfig implements WebMvcConfigurer{ }重寫 configureDefaultServletHandling() 方法,啟動(dòng) Servlet 的 default Servlet 來(lái)處理靜態(tài)資源;public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable();}再次請(qǐng)求 http://localhost:8888/sm-demo/static.html ,你應(yīng)該能看到靜態(tài)頁(yè)面的內(nèi)容。

2. Django

Django是 Full-Stack Web 框架的代表,功能非常全面和成熟,開(kāi)發(fā)文檔很完備。它在Python Web開(kāi)發(fā)框架的占有率應(yīng)該是第一。Django 的宗旨就是盡可能的提供所有功能,讓你用盡可能少的代碼完成業(yè)務(wù)。Django 遵循了 MVC 開(kāi)發(fā)模式,并將這個(gè)模式命名為 MTV ( MTV 模式是 Python 中獨(dú)有的):M Model(數(shù)據(jù)模型,用于后端數(shù)據(jù)庫(kù)模型定義和處理模塊);T Templates(模版,用于前端顯示信息);V View(視圖,用于接收客戶端請(qǐng)求、處理Model、渲染返回信息給客戶端等)。優(yōu)點(diǎn):各種組件集成高度成熟,配置齊全;用戶模型、權(quán)限認(rèn)證體系健全;ORM數(shù)據(jù)庫(kù)管理功能簡(jiǎn)單方便;自帶后臺(tái)管理功能。缺點(diǎn):配置相對(duì)復(fù)雜;數(shù)據(jù)庫(kù) ORM 組裝出來(lái)的 sql 語(yǔ)句性能較差。Django安裝通過(guò) pip 直接安裝:pip install Django 通過(guò)源碼下載并安裝:git clone https://github.com/django/django.git Tips: 我們將在下一節(jié)講解如何在 PyCharm 創(chuàng)建基于Django框架的 Web 項(xiàng)目。

2. 為什么要學(xué)習(xí) ThinkPHP?

對(duì)于剛開(kāi)始學(xué)習(xí) PHP 的初級(jí)程序員來(lái)說(shuō),把基礎(chǔ)的 PHP 知識(shí)掌握之后,就需要進(jìn)階到框架層面的知識(shí)了。ThinkPHP 框架上手容易,學(xué)習(xí)資料豐富,對(duì)新手朋友來(lái)說(shuō)非常友好。ThinkPHP 采用 MVC 思想開(kāi)發(fā)的,它的主要活躍社區(qū)在國(guó)內(nèi),免費(fèi)開(kāi)源,其配置開(kāi)發(fā)相對(duì)容易、迅捷,非常適合新手的 PHP 框架。ThinkPHP 是一個(gè)輕量級(jí)的開(kāi)發(fā)框架(比較小,僅提供一部分功能,可拓展很多第三方功能),學(xué)習(xí) ThinkPHP 之后,可以快速發(fā)開(kāi)一些中小型項(xiàng)目,并且能對(duì) PHP 語(yǔ)言基礎(chǔ)有更深入的理解。作為一個(gè)整體開(kāi)發(fā)解決方案,ThinkPHP 能夠解決應(yīng)用開(kāi)發(fā)中的大多數(shù)需要,因?yàn)槠渥陨戆说讓蛹軜?gòu)、兼容處理、基類庫(kù)、數(shù)據(jù)庫(kù)訪問(wèn)層、模板引擎、緩存機(jī)制、插件機(jī)制、角色認(rèn)證、表單處理等常用的組件,并且對(duì)于跨版本、跨平臺(tái)和跨數(shù)據(jù)庫(kù)移植都比較方便。

3.3 主 Activity 邏輯

Activity 的邏輯其實(shí)和 ListView 中的例子完全一樣,只需要將所有的 ListView 類型改成 GridView 即可。這里體現(xiàn)了 MVC 設(shè)計(jì)思路的靈活性,我們想要替換一個(gè)樣式其實(shí)只需要修改布局文件,主邏輯和數(shù)據(jù)層完全不需要修改,這就是前面所說(shuō)的 UI 和數(shù)據(jù)解耦的強(qiáng)大優(yōu)勢(shì)。MainActivity 代碼如下:package com.emercy.myapplication;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.GridView;import android.widget.Toast;public class MainActivity extends Activity { GridView mGridView; String[] mDataName = {"蘋果", "梨", "香蕉", "桃子", "西瓜", "荔枝", "橘子"}; int[] mDataImage = {R.drawable.apple, R.drawable.pear, R.drawable.banana, R.drawable.peach, R.drawable.watermelon, R.drawable.lychee, R.drawable.orange, R.drawable.orange}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGridView = findViewById(R.id.gridview); MyAdapter adapter = new MyAdapter(this); adapter.setData(mDataName, mDataImage); mGridView.setAdapter(adapter); mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Toast.makeText(getApplicationContext(), mDataName[i % mDataName.length], Toast.LENGTH_LONG).show(); } }); }}編譯之后,可以發(fā)現(xiàn)從一維列表變成了網(wǎng)格列表,水果的樣式循環(huán) 10 次,效果如下:

2. 對(duì)象 / 表單

以表單的方式提交數(shù)據(jù)有一個(gè)優(yōu)點(diǎn),可以把邏輯上具有內(nèi)在聯(lián)系的多個(gè)數(shù)據(jù)同時(shí)發(fā)送給服務(wù)器。原生 Servlet 開(kāi)發(fā)時(shí),服務(wù)器端的響應(yīng)組件(Servlet)中,需要開(kāi)發(fā)者編寫代碼從請(qǐng)求包一個(gè)一個(gè)解析出提交過(guò)來(lái)的數(shù)據(jù)。如果數(shù)據(jù)量不多,倒還好,如果數(shù)據(jù)量較多,一個(gè)一個(gè)解析,枯燥乏味的工作除了讓人厭煩,且會(huì)耽誤開(kāi)發(fā)效率。來(lái)!通過(guò)一個(gè)案例,體會(huì) Spring MVC 是如何一步到位解析大量數(shù)據(jù)的。案例需求描述: 實(shí)現(xiàn)用戶注冊(cè)功能。流程分析: 通過(guò)注冊(cè)頁(yè)面,用戶輸入個(gè)人信息。表單中的數(shù)據(jù)以 POST 的請(qǐng)求方式提交至服務(wù)器,服務(wù)器端的控制器對(duì)提交過(guò)來(lái)的數(shù)據(jù)進(jìn)行處理。實(shí)現(xiàn)流程:

2. 使用注解解析數(shù)據(jù)

原生 Servlet 開(kāi)發(fā)過(guò)程中,開(kāi)發(fā)者定義的 Servlet 具有請(qǐng)求響應(yīng)功能。因?yàn)?J2EE 中的 Servlet 僅僅只是提供了編寫企業(yè)級(jí)應(yīng)用程序的規(guī)范,并沒(méi)有提供更多實(shí)質(zhì)性的功能。在執(zhí)行響應(yīng)邏輯之前或之后需要開(kāi)發(fā)者編寫一些通用的功能代碼。如解析請(qǐng)求包中的數(shù)據(jù)、構(gòu)建響應(yīng)路徑……Spring MVC 提供了很多實(shí)用的注解,用來(lái)解析請(qǐng)求包、自動(dòng)綁定請(qǐng)求包中不同位置的數(shù)據(jù)。在使用注解解析請(qǐng)求包中的數(shù)據(jù)前,先了解一下請(qǐng)求包的格式。WEB 應(yīng)用程序中, 所謂的請(qǐng)求包是指遵循 HTTP 協(xié)議的一種數(shù)據(jù)格式包。在某些文章中,稱請(qǐng)求包為報(bào)文。一個(gè)完整的請(qǐng)求包應(yīng)該由 3 個(gè)部分組成:請(qǐng)求行: 包括請(qǐng)求方法、請(qǐng)求的資源地址(URL) 、HTTP 協(xié)議版本號(hào);消息頭: 消息頭是傳送給服務(wù)器的信息,以 key:value 的格式描述;實(shí)體部分或報(bào)文體: 以 key=value 的數(shù)據(jù)格式保存客戶端傳遞給應(yīng)用程序的數(shù)據(jù)。

2.2 使用表達(dá)式限定請(qǐng)求

@RequestMapping 注解的映射描述具有多樣性:支持標(biāo)準(zhǔn)的 URL 格式;支持 Ant 風(fēng)格。什么是 Ant 風(fēng)格?所謂 Ant 風(fēng)格指在 URL 中支持 通配符的語(yǔ)法結(jié)構(gòu)描述。 Ant 的通配符主要是 3 種:?: 匹配任何單字符;* : 匹配 0 個(gè)或者任意數(shù)量的字符;** : 匹配 0 個(gè)或者更多的目錄。如下面的地址請(qǐng)求映射:/user/*/saveUser:可匹配類似于 /user/aaa/saveUser、/user/bbb/saveUser 等請(qǐng)求 URL;/user/**/saveUser:可以匹配 /user/saveUser、/user/aaa/bbb/saveUser 等請(qǐng)求 URL;Tips : ** 可以表示多個(gè)目錄。/user/saveUser??:匹配 /user/saveUseraa、/user/saveUserbb 等請(qǐng)求 URL;Spring MVC 的地址請(qǐng)求映射除了支持通配符外,還支持帶 {xxx} 占位符的 URL。如下面的地址請(qǐng)求映射:/user/{userId}:可以匹配 user/1、user/2、user/123 等請(qǐng)求 URL;/user/**/{userId}:可以匹配 user/aa/bbb/1、user/aaa/45 等請(qǐng)求 URL;company/{companyId}/user/{userId}/detail:可以匹配 company/1/user/2/detail 等請(qǐng)求 URL。

3.1 請(qǐng)求分流

瀏覽器向 Spring MVC 程序發(fā)起的所有請(qǐng)求都會(huì)匯流給 DispatcherServlet 組件。再由 DispatcherServlet 分流到具體的用戶控制器;為什么要對(duì)所有請(qǐng)求集中分流?可以從 2 個(gè)維度理解:安全性: 如同去拜訪某一個(gè)公司,所有的來(lái)訪人員都要經(jīng)由前臺(tái)工作人員登記、確認(rèn)后才會(huì)被引導(dǎo)到具體的會(huì)客室,前臺(tái)可以對(duì)來(lái)訪人員的身份進(jìn)行初步認(rèn)定和篩選。請(qǐng)求分流的性質(zhì)也是如此,確保只能通過(guò)一個(gè)入口進(jìn)入程序;標(biāo)準(zhǔn)化: 每一個(gè)請(qǐng)求都會(huì)以相同的方式進(jìn)行分流處理。如同造訪公司,如果對(duì)每一個(gè)人的來(lái)訪有區(qū)別或者說(shuō)沒(méi)有統(tǒng)一的接待標(biāo)準(zhǔn),一定會(huì)產(chǎn)生額外的工作量。統(tǒng)一協(xié)調(diào),標(biāo)準(zhǔn)化項(xiàng)目,可以高度簡(jiǎn)化處理流程。

2.2 重定向

Spring MVC 中使用重定向很簡(jiǎn)單,只需要在返回值中添加 redirect 關(guān)鍵字。@RequestMapping("/response03")public String response03(ModelMap model) throws IOException { //發(fā)送給客戶端的響應(yīng)數(shù)據(jù) String hello="Hello"; model.addAttribute("data", hello); return "redirect:/hello";}重定向和轉(zhuǎn)發(fā)的本質(zhì)區(qū)別在于如何找到視圖。轉(zhuǎn)發(fā)是控制器自己找的,也就是在服務(wù)器端找的。重定向則是先把視圖地址寫入響應(yīng)包,然后發(fā)送瀏覽器,意思是說(shuō),瀏覽器,麻煩你自己找一下。瀏覽器獲取到響應(yīng)包中的地址后再發(fā)送一次請(qǐng)求,找到視圖,然后,把數(shù)據(jù)模型中的數(shù)據(jù)讀出來(lái)顯示在頁(yè)面中。相比較轉(zhuǎn)發(fā),重定向會(huì)多一次請(qǐng)求,也意味著數(shù)據(jù)模型中的數(shù)據(jù)需要在跨請(qǐng)求間被解析到。另外,視圖文件必須放置在瀏覽器能訪問(wèn)到的位置。如果視圖文件放在 WEB-INF 目錄下,則重定向是不能訪問(wèn)到的。

2.4 限定請(qǐng)求參數(shù)

限定請(qǐng)求參數(shù)和限定請(qǐng)求方法同工異曲。所謂限定請(qǐng)求參數(shù),Spring MVC 會(huì)檢查請(qǐng)求包中是否包含符合要求的請(qǐng)求參數(shù)。通過(guò) @RequestMapping 注解中的 params() 方法實(shí)現(xiàn)參數(shù)篩選。如下面的實(shí)例:@RequestMapping(value="/test", params="userId") public String test(){ ... }test()方法只會(huì)響應(yīng)請(qǐng)求包中包含有 userId 參數(shù)的 URL。params()方法支持條件運(yùn)算符構(gòu)建的表達(dá)式。params=“userId”: 指揮響應(yīng)請(qǐng)求包中包含有名為 userId 參數(shù)的請(qǐng)求;params="!userId" : 如果請(qǐng)求包中有名為 userId 的請(qǐng)求參數(shù),則不響應(yīng),否則響應(yīng);params=“userId!=1”: 對(duì)響應(yīng)的請(qǐng)求有更多的要求,除了請(qǐng)求包中必須包含 userId 參數(shù)外,其值必須是 1;params={“userId=1”,“userName”}: 響應(yīng)的條件是,請(qǐng)求包中必須包含名為 userId 和 userName 這兩個(gè)參數(shù),且 userId 參數(shù)的值必須為 1。Tips : 方法、參數(shù)限制可同時(shí)使用。@RequestMapping(value="/test",method = RequestMethod.POST,params = {"userId"})public String test() { return null;}

2.1 JSR 是什么

Tips: 不要看錯(cuò)了,是 JSR 不是 JSP。JSR: Java 官方提供的數(shù)據(jù)合法性標(biāo)準(zhǔn)驗(yàn)證框架,它只是一個(gè)規(guī)范?,F(xiàn)有多個(gè)版本:Bean Validation 2.0 (JSR 380) ;Bean Validation 1.1 (JSR 349);Bean Validation 1.0 (JSR 303)。準(zhǔn)確的講,Spring MVC 驗(yàn)證框架只是集成了 JSR 驗(yàn)證框架,并沒(méi)有太多自己的具體實(shí)現(xiàn)。 JSR 提供了很多驗(yàn)證注解,一般放在要驗(yàn)證的 Bean 類型的屬性前面。@Null: 被注解的屬性的值必須為空;@NotNull: 被注解的屬性的值可以不為空;@Min(value): 注解數(shù)字類型的屬性,其值大于等于指定的值;@Max(value): 注解數(shù)字類型的屬性,其值小于等于指定值;@Size(max, min): 注解的屬性值的大小必須是在給定的范圍內(nèi)(包括邊界數(shù)字);@Past: 注解日期類型屬性,必須是一個(gè)過(guò)去的日期;@Future: 注解日期類型屬性,必須是一個(gè)將來(lái)的日期;@Pattern(regexp): 使用正則表達(dá)式驗(yàn)證屬性的值;@Length(min,max): 屬性值的長(zhǎng)度在給定的范圍之內(nèi)(包括邊界數(shù)字)。Tips: 更多的驗(yàn)證注解大家可以查閱 JSR 官方文檔。了解了這些注解后,現(xiàn)在開(kāi)始使用。

3. Thymeleaf 的特點(diǎn)

Thymeleaf 與其它的視圖技術(shù)相比較,最大的優(yōu)點(diǎn)在于動(dòng)靜結(jié)合。何謂動(dòng)靜給合?Thymeleaf 的模板是純正的 html 代碼。Thymeleaf 提供的模板語(yǔ)法指令都是以 HTML 標(biāo)簽屬性方式嵌入進(jìn)去的,沒(méi)有為頁(yè)面添加額外的元素,頁(yè)面的整體風(fēng)格不會(huì)被破壞。當(dāng)運(yùn)行在服務(wù)器端時(shí),才會(huì)由模板引擎解析。如果直接由瀏覽器打開(kāi),瀏覽器會(huì)忽視 Thymeleaf 指令屬性,把模板文件當(dāng)成 HTML 代碼,可以直接在瀏覽器顯示。動(dòng)靜結(jié)合的優(yōu)點(diǎn):不影響前后端工程師對(duì)頁(yè)面的設(shè)計(jì)和調(diào)整;沒(méi)有在頁(yè)面中侵入非 HTML 語(yǔ)言代碼,保持了原始頁(yè)面的風(fēng)格。除了動(dòng)靜給合,還有一個(gè)較大的特點(diǎn)就是與 Spring MVC 或 Spring Boot 完美結(jié)合,Spring 提供有對(duì)接 Thymeleaf 的接口組件,使用起來(lái)方便直接。正因?yàn)?Thymeleaf 的優(yōu)點(diǎn),建議作為項(xiàng)目開(kāi)發(fā)中的首選方案。

2. 響應(yīng)的本質(zhì)

Spring MVC 項(xiàng)目中的用戶控制器用來(lái)處理用戶的請(qǐng)求,無(wú)論處理的結(jié)果如何,都需要給用戶一個(gè)響應(yīng),HTTP 響應(yīng)包可以說(shuō)是這個(gè)響應(yīng)結(jié)果的載體。理論上講,用戶控制器處理完請(qǐng)求,得到的結(jié)果數(shù)據(jù)可以直接寫入到響應(yīng)包中。@Controllerpublic class ResponseAction {@RequestMapping("/response01")public void response01(HttpServletResponse response) throws IOException { //發(fā)送給客戶端的響應(yīng)數(shù)據(jù) String hello="hello"; PrintWriter out =response.getWriter(); out.write(hello); out.close();}}把需要響應(yīng)給客戶端的數(shù)據(jù)寫入響應(yīng)包中便是響應(yīng)的本質(zhì)。如果僅僅只是把數(shù)據(jù)發(fā)送給客戶端,數(shù)據(jù)在瀏覽器中顯示時(shí),出來(lái)的樣式會(huì)過(guò)于簡(jiǎn)單、甚至丑陋。要解決這個(gè)問(wèn)題,也好辦,發(fā)送數(shù)據(jù)時(shí),也附帶發(fā)送數(shù)據(jù)格式。Tips:如果客戶端只需要純數(shù)據(jù),如 JSON 格式,則可以直接使用上面的方法。修改上面的響應(yīng)數(shù)據(jù):String hello="<font color=\"red\">hello</font>";這時(shí),在瀏覽器中不僅能看到數(shù)據(jù),還能用設(shè)計(jì)好的樣式顯示出來(lái)。初期 WEB 開(kāi)發(fā),便采用了這種 “數(shù)據(jù) + 樣式” 的方式。因初期頁(yè)面中數(shù)據(jù)并不是很多,人為對(duì)于頁(yè)面無(wú)素顯示也沒(méi)有多大需求。但是,隨著項(xiàng)目功能越來(lái)越大,數(shù)據(jù)量成倍增加,比如說(shuō)商城首頁(yè),需要顯示當(dāng)前登錄者信息、商品信息、推薦的商品信息、用戶瀏覽信息…… 并且用戶對(duì)最終顯示結(jié)果也提出了更多要求,如美觀、大方、整潔……如果還是如前面一樣,把數(shù)據(jù)和 HTML 一起編織在一起,然后響應(yīng)給客戶端,代碼將變得丑陋不堪。新的解決方案是采用組件化開(kāi)發(fā)思想:控制器處理數(shù)據(jù),視圖組件提供模板樣式用來(lái)顯示最終數(shù)據(jù)。所以在構(gòu)建響應(yīng)包時(shí),控制器需要 2 方面信息:數(shù)據(jù):由控制器返回;視圖:由視圖解析器組件維護(hù)。Spring MVC 提供數(shù)據(jù)模型組件充當(dāng)數(shù)據(jù)和視圖之間的橋梁??刂破飨劝烟幚砗蟮臄?shù)據(jù)保存到數(shù)據(jù)模型中;找到視圖,由視圖從數(shù)據(jù)模型中取得數(shù)據(jù),并顯示在視圖中。重定向和轉(zhuǎn)發(fā)的區(qū)別在于尋找視圖的方式。

2.2 測(cè)試流程

在項(xiàng)目的 WEB-INF 目錄下新建 templates 目錄,并在此目錄下新建名為 hello.html 的文件。Tips: hello.html 雖然擴(kuò)展名是 html。 其實(shí)是遵循 Thymeleaf 模板語(yǔ)法規(guī)范的模板文件。本課程主要講解在 Spring MVC 中如何使用 Thymeleaf , 會(huì)講解一點(diǎn) Thymeleaf 模板語(yǔ)法,但更多的了解需要你移步到 Thymeleaf 的官方網(wǎng)站:https://www.thymeleaf.org/。hello.html 文件的內(nèi)容:<div> <table> <thead> <tr> <th>name</th> <th>password</th> </tr> </thead> <tbody> <tr> <td th:text="${user.userName}"></td> <td th:text="${user.userPassword}"></td> </tr> </tbody> </table></div>Tips: hello.html 文件內(nèi)容和普通的 HTML 頁(yè)面沒(méi)有多大的區(qū)別,區(qū)別于在 HTML 頁(yè)面標(biāo)簽中使用了 Thymeleaf 提供的一些語(yǔ)法元素,如:th:text 用來(lái)動(dòng)態(tài)讀取作用域中的數(shù)據(jù)。編寫控制器;@Controller@RequestMapping("/thymeleaf")public class ThymeleafAction { @RequestMapping("/hello") public String thymeleaf(ModelMap map) { User user=new User("mk", "123456"); map.addAttribute("user", user); return "hello"; }}發(fā)布項(xiàng)目、啟動(dòng) tomcat、打開(kāi)瀏覽器,在瀏覽器中輸入: http://localhost:8888/sm-demo/thymeleaf/hello。Tips: 再聲明一下,為了讓 Thymeleaf 的測(cè)試更干凈,注釋或刪除掉原來(lái)配置過(guò)的視圖技術(shù)相關(guān)信息。Thymeleaf 的語(yǔ)法元素也稱其為指令,以 th 開(kāi)頭,如前面用到的 th:text。

1. 前言

每逢春暖花開(kāi)的時(shí)節(jié),我都會(huì)想起大學(xué)時(shí)代。那時(shí)候的我,在陽(yáng)光明媚的日子里,坐在圖書館的落地窗前。桌子上是一疊 Java Web 書本,還有我那破破卻可愛(ài)的筆記本電腦。你是否也偶爾懷念,大學(xué)時(shí)代的似水流年(圖片來(lái)源于網(wǎng)絡(luò),版權(quán)歸原作者所有)那是 SSH 風(fēng)華正茂的年代,Spring 如日中天,負(fù)責(zé)整合各種框架,儼然一副老大哥的樣子;Hibernate 是數(shù)據(jù)持久層的不二之選,iBatis 在它面前就像個(gè)小老弟;Struts 則是 MVC 框架的形象代言,不懂點(diǎn) Struts 都不好意思說(shuō)在做 Web 開(kāi)發(fā)。而我卻總是,被 SSH 繁瑣的配置困擾。SSH 各有一大堆配置,當(dāng)他們碰到一起,還需要額外互相配置。就像三個(gè)老朋友,每次再重逢,還要互相介紹。做一個(gè)簡(jiǎn)單的項(xiàng)目,竟有一大半時(shí)間在配置。不是在編輯配置文件的路上,就是在修復(fù)配置錯(cuò)誤的途中。程序開(kāi)發(fā)不應(yīng)該是簡(jiǎn)單而優(yōu)雅的嗎?正如我們所追求的生活。

2.1 添加日志框架

本小節(jié)主要介紹在 Spring MVC 項(xiàng)目中如何集成 log4j 2 日志系統(tǒng)。打開(kāi)項(xiàng)目的 pom.xml 文件,添加 log4j 的依賴包;<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.10.0</version></dependency><dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version></dependency><dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>2.10.0</version></dependency>Tips: 這里有 3 個(gè)依賴包,log4j-web 是針對(duì)于 WEB 應(yīng)用程序的依賴包。新建名為 log4j2.xml 的配置文件;Tips: log4j2 不再支持 properties 格式的文件,只支持 xml,json 或是 yaml,不指定位置的情況下默認(rèn)在 src/main/resources 下查找。提供如下最基礎(chǔ)的配置內(nèi)容:<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> <RollingRandomAccessFile name="smlog" fileName="sm.log" filePattern="$${date:yyyy-MM}/sm-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" /> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="10 MB" /> </Policies> <DefaultRolloverStrategy max="20" /> </RollingRandomAccessFile> </Appenders> <Loggers> <Logger name="org.springframework" level="DEBUG" /> <Root level="info"> <AppenderRef ref="Console" /> <AppenderRef ref="smlog" /> </Root> </Loggers></Configuration>log4j2 配置內(nèi)容簡(jiǎn)要說(shuō)明:Appender: 信息輸出位置,可以有多個(gè)輸出口。 SYSTEM_OUT 的目標(biāo)是 Console 。表示把日志內(nèi)容輸出到控制臺(tái)上。Root Logger 的級(jí)別是 info。所有 info 及以上級(jí)別的日志才會(huì)記錄;Tips: 日志級(jí)別分別有 TRACE、 DEBUG 、NFO 、WARN 、ERROR 、 FATAL 這幾種,日志級(jí)別從左向右依次增加。日志信息的輸出由當(dāng)前日志級(jí)別決定,只有比當(dāng)前級(jí)別高的信息才能輸出。RollingRandomAccessFile: 表示以文件方式記錄??梢栽O(shè)置日志文件的文件名以及格式,一般會(huì)加上時(shí)間戳;Tips: 本文側(cè)重于講解在 Spring MVC 項(xiàng)目中如何使用 log4j 日志系統(tǒng)。log4j 其它的配置信息大家可以查閱官方文檔: 。如果希望日志信息既輸出到控制臺(tái),又能輸出到文件中,務(wù)必使用 AppenderRef 標(biāo)簽引用控制臺(tái)配置名稱和文件配置名稱。<Root level="info"> <AppenderRef ref="Console" /> <AppenderRef ref="smlog" /></Root>log4j2 的配置文件開(kāi)發(fā)者可以根據(jù)需要存放在其它位置,但需要在 web.xml 文件中配置 log4j 提供的監(jiān)聽(tīng)器。<context-param> <param-name>log4jConfiguration</param-name> <param-value>classpath:log4j2.xml</param-value></context-param><listener> <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class></listener>Tips: 最佳方案是把 log4j 的 log4j2.xml 配置文件放在默認(rèn)位置,避開(kāi)上面的配置。Servlet2.5 以上,可以不用配置監(jiān)聽(tīng)器。使用測(cè)試。使用很簡(jiǎn)單,在你需要使用日志的地方,創(chuàng)建一個(gè)日志對(duì)象。public class Test { static Logger logger = LogManager.getLogger(Test.class); public static void main(String[] args) { logger.info("info","messgae"); }}運(yùn)行上面代碼,除了在控制臺(tái)上輸出信息外,且還會(huì)把內(nèi)容寫入到日志文件中。日志對(duì)象的 i 常用方法如下:debug():輸出 debug 級(jí)別信息;error():輸出 error 級(jí)別的信息;fatal():輸出 fatal 級(jí)別的信息;info():輸出 info 級(jí)別的信息;trace():輸出 trace 級(jí)別的信息;warn():輸出 warn 級(jí)別的信息。以上幾個(gè)方法除了語(yǔ)義上的區(qū)別,使用起來(lái)沒(méi)有本質(zhì)的區(qū)別。通過(guò)語(yǔ)義上的差異性,log4j 可以控制信息的輸出級(jí)別。

3.3 Spring 的核心功能

大家對(duì)于使用 Spring 框架開(kāi)發(fā)項(xiàng)目已經(jīng)司空見(jiàn)慣了… 但是對(duì)于它的功能或者作用,描述出來(lái)總是差點(diǎn)什么,那么現(xiàn)在咱們?cè)敿?xì)聊一聊它的核心功能。核心功能:控制反轉(zhuǎn)(IoC): 簡(jiǎn)單理解 IoC 是一種設(shè)計(jì)模式,將實(shí)例化對(duì)象的控制權(quán) 由手動(dòng)的 new 變成了 Spring 框架通過(guò)反射機(jī)制實(shí)例化;依賴注入(DI): 首先理解依賴,程序運(yùn)行的需要可以稱之為依賴。由于 Spring 框架通過(guò)反射技術(shù)實(shí)例化了對(duì)象,并將對(duì)象的實(shí)例存入在容器進(jìn)行管理。那么如果一個(gè)類中的屬性為某個(gè)其余的類,屬性無(wú)需手動(dòng)賦值,通過(guò) spring 的配置文件,或者 Spring 提供的注解,通過(guò) spring 框架可以實(shí)現(xiàn)直接注入屬性;面向切面編程 (AOP): 何謂切面,切面是數(shù)學(xué)中的一個(gè)概念,表示只有一個(gè)點(diǎn)接觸到球體的一個(gè)平面稱呼為切面,而接觸點(diǎn)稱呼為切點(diǎn)。那么在 Spring 中,切面編程指的就是在程序運(yùn)行某個(gè)方法的時(shí)候,不修改原始執(zhí)行代碼邏輯,由程序動(dòng)態(tài)地執(zhí)行某些額外的功能,對(duì)原有的方法做增強(qiáng),這就叫做面向切面編程,那個(gè)被監(jiān)測(cè)的執(zhí)行方法,稱呼為切入點(diǎn)。知識(shí)小結(jié):Spring 是分層的 Java SE/EE 應(yīng)用 輕量級(jí)開(kāi)源框架,以 IoC(Inverse of Control:控制反轉(zhuǎn))和 AOP(Aspect Oriented Programming:面向切面編程)為內(nèi)核,提供了展現(xiàn)層 Spring MVC 和持久層 Spring JDBC 以及業(yè)務(wù)層事務(wù)管理等眾多的企業(yè)級(jí)應(yīng)用技術(shù),還能整合開(kāi)源世界眾多 著名的第三方框架和類庫(kù), 是使用最多的 Java EE 企業(yè)應(yīng)用開(kāi)源框架。使用 Spring 的意義在于:對(duì)于 bean 對(duì)象的實(shí)例管理更加方便,代碼編寫更加優(yōu)雅,降低代碼的耦合性,提升代碼的擴(kuò)展性。

2.2 實(shí)現(xiàn)流程

準(zhǔn)備工作完成,現(xiàn)在實(shí)現(xiàn)文件上傳。編寫提交表單;<form action="upload" method="POST" enctype="multipart/form-data"> 選擇文件:<input type="file" name="file" value="" /> <br /> <input type="submit" name="upload" value="上傳" /></form>表單的 enctype 屬性有如下幾個(gè)選擇:application/x-www-form-urlencoded : 在發(fā)送前編碼所有字符,數(shù)據(jù)以字符串的方式發(fā)送;multipart/form-data: 不對(duì)字符編碼,使用包含文件上傳控件的表單時(shí),必須使用該值;text/plain: 空格轉(zhuǎn)換為 “+” 加號(hào),但不對(duì)特殊字符編碼。Tips: 因?yàn)楸韱沃邪形募蟼骺丶?,所以,一定要設(shè)置表單的 enctype 值為 multipart/form-data。獲取項(xiàng)目上下文絕對(duì)路徑;編寫控制器之前,先打開(kāi) web.xml ,注冊(cè)一個(gè) org.springframework.web.util.WebAppRootListener 監(jiān)聽(tīng)器,通過(guò)此監(jiān)聽(tīng)器獲取到 Spring MVC 項(xiàng)目的發(fā)布的絕對(duì)路徑,用來(lái)為上傳的文件指定存儲(chǔ)位置。<context-param> <param-name>webAppRootKey</param-name> <param-value>webapp.root</param-value></context-param><listener> <listener-class>org.springframework.web.util.WebAppRootListener</listener-class></listener>Tips: webapp.root 相當(dāng)于一個(gè)變量,可以是符合規(guī)范的任意命稱。當(dāng)程序啟動(dòng)時(shí),此監(jiān)聽(tīng)器會(huì)把服務(wù)器絕對(duì)路徑保存在此變量中。使用監(jiān)聽(tīng)器的方式獲取路徑可以有效地減少開(kāi)發(fā)者的編碼量。當(dāng)然,完全可以不使用此監(jiān)聽(tīng)器,開(kāi)發(fā)者可以在控制器中通過(guò)注入原生 Servlet API 編碼獲取。編寫控制器:@Controllerpublic class UpLoadAction { @RequestMapping("/upload") public String upload(@RequestPart("upFile") byte[] file) throws IOException { String path = System.getProperty("webapp.root"); String filePath = path + "\\upload\\temp.png"; FileOutputStream fileOutputStream = new FileOutputStream(filePath); FileCopyUtils.copy(file, fileOutputStream); return "success"; }}解釋上面的代碼:System.getProperty(“webapp.root”) 可以得到監(jiān)聽(tīng)器組件得到的項(xiàng)目上下文路徑。在項(xiàng)目的根目錄下新建 upload 目錄,用來(lái)存儲(chǔ)上傳過(guò)來(lái)的文件;@RequestPart(“upFile”) 注解能注入表單提交上來(lái)的文件數(shù)據(jù),此數(shù)據(jù)以 byte[] 類型保存。使用 @RequestPart(“upFile”) 注解的方式存在些問(wèn)題,不能獲取上傳文件的文件名等其它元數(shù)據(jù)信息。實(shí)例測(cè)試。打開(kāi)瀏覽器,顯示上傳頁(yè)面。在本地首先選擇好需要上傳的文件,然后點(diǎn)擊上傳。找到 tomcat 中的項(xiàng)目發(fā)布目錄,可以找到剛上傳的文件。

3. 各種語(yǔ)言的 Web 框架介紹

目前,主流的 Web 框架可以按照語(yǔ)言類型進(jìn)行分類,比如基于 Java 開(kāi)發(fā)的 Web 框架、基于 Python 開(kāi)發(fā)的 Web 框架和基于 Go 開(kāi)發(fā)的 Web 框架等等。每種語(yǔ)言領(lǐng)域內(nèi)的 Web 框架也是各有特色,有大而全,有小而精,還有專注異步高性能等等。熱門的 Python Web 框架有:Django:基于 MTV 的框架模式,有強(qiáng)大的數(shù)據(jù)庫(kù)功能、強(qiáng)大的后臺(tái)管理功能、模板系統(tǒng)、緩存系統(tǒng)等;Flask:小而精的 Web 框架典范,可擴(kuò)展性強(qiáng);Tornado: 輕量級(jí)的 Web 框架,其特點(diǎn)是非阻塞和高性能,是實(shí)時(shí) Web 服務(wù)的一個(gè) 理想框架。主流的 Java Web 框架有:Spring/Spring Boot/Spring MVC 等:幾乎是大部分 Java web 開(kāi)發(fā)者的首選和必選,占據(jù)了大部分市場(chǎng)?;?Spring 及其衍生框架,我們能迅速開(kāi)發(fā)一個(gè) Java Web 服務(wù),幾乎不需要任何 Web 開(kāi)發(fā)基礎(chǔ);Dubbo:阿里巴巴的開(kāi)源的高性能 RPC 框架、特點(diǎn)是分布式、高性能以及高度可擴(kuò)展;Struts2:老一代的 Java Web 框架,特點(diǎn)是高度成熟。不過(guò)目前趨勢(shì)來(lái)看,已經(jīng)很少人使用 Struts2 來(lái)開(kāi)發(fā)新的 Web 服務(wù)。Go 作為近幾年快速崛起的后端開(kāi)發(fā)語(yǔ)言,也受到了廣大后端開(kāi)發(fā)者的追捧,Go Web 框架也隨之而來(lái),其中的典型代表有:Beego 框架:它類似于 Python Web 框架 Django,走大而全的風(fēng)格,具備各種 Web 應(yīng)用程序的通用功能;Gin 框架:Gin 是 Go 的一個(gè)微框架,封裝優(yōu)雅,接口友好。具有快速靈活,容錯(cuò)方便、性能優(yōu)異等特點(diǎn);Echo 框架:Go 的微型 Web 框架。其具備快速 HTTP 路由器、支持?jǐn)U展中間件,同時(shí)還支持靜態(tài)文件服務(wù)。

2.2 返回對(duì)象

JAVA 中的數(shù)據(jù)很多時(shí)候都是以 OOP 的形式存在的,如學(xué)生對(duì)象數(shù)據(jù)、老師對(duì)象數(shù)據(jù)、用戶對(duì)象數(shù)據(jù)……那么,控制器中的方法能不能直接把數(shù)據(jù)以對(duì)象為單位寫入響應(yīng)包后返回給瀏覽器了?如下面的實(shí)例:@RequestMapping("/test02")@ResponseBodypublic User testJson01() { return new User("mk", "123");}打開(kāi)瀏覽器,在地址欄上輸入:http://localhost:8888/sm-demo/json/test02 。在瀏覽器你將看到如下圖所示結(jié)果:拋異常了。對(duì)于出錯(cuò),大家應(yīng)該有預(yù)感。User 是 JAVA 語(yǔ)言中的類類型,對(duì)于瀏覽器而言對(duì)它的了解是一片空白。但是,為什么前面返回字符串時(shí)卻可以了?那是因?yàn)樽址彩且环N通用類型,瀏覽器沒(méi)有不認(rèn)識(shí)的道理,但是,User 類型,瀏覽器只能摸后腦勺了。如果想讓瀏覽器識(shí)別出 User 類型數(shù)據(jù)。想想也簡(jiǎn)單,自己編碼,把對(duì)象數(shù)據(jù)轉(zhuǎn)換成字符串格式。@RequestMapping("/test03")@ResponseBodypublic String testJson03() { User user=new User("mk", "123"); return user.getUserName()+","+user.getUserPassword();}經(jīng)過(guò)上面的修改后,瀏覽器中能顯示出數(shù)據(jù)。但是,這里會(huì)有 2 個(gè)問(wèn)題需要思考一下:如前所述,前后端分離最主要的思想是讓前端承擔(dān)一部分?jǐn)?shù)據(jù)業(yè)務(wù)邏輯。一串沒(méi)有特定格式的字符串傳遞給前端,真要交給 JS 處理,你還真不怕 JS 煩心,你叫它如何從中識(shí)別出誰(shuí)是誰(shuí);直接返回值給瀏覽器之前,需要通過(guò)手工編碼的方式把 OOP 數(shù)據(jù)格式轉(zhuǎn)換成字符串,這番折騰,勞心勞力。好!先解決第一個(gè)問(wèn)題。字符串?dāng)?shù)據(jù)類型是非結(jié)構(gòu)化的,但是,可以把它轉(zhuǎn)換成具有特定結(jié)構(gòu)格式的 JSON 字符串。@RequestMapping("/test04")@ResponseBodypublic String testJson04() { User user = new User("mk", "123"); String json = "{\"userName\":\"" + user.getUserName() + "\",\"userPassWord\":" + "\"" + user.getUserPassword() + "\"" + "}"; return json; }打開(kāi)瀏覽器,地址欄中輸入 http://localhost:8888/sm-demo/json/test04 。瀏覽器中將顯示如下信息:傳遞給瀏覽器的雖然還是字符串,但是是具有特定格式的 JSON 字符串,如果要交給 JS 處理,JS 表示很開(kāi)心。是的,數(shù)據(jù)格式的問(wèn)題解決了,但是,編碼的工作量增加了很多。其實(shí),你所想要的結(jié)果,Spring MVC 能輕松幫你實(shí)現(xiàn)。

首頁(yè)上一頁(yè)123456下一頁(yè)尾頁(yè)
直播
查看課程詳情
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)