這次使用 gradle,創建好 gradle 後,預設不是 Web 的,使用以下方式變成 Web
※變 Web 專案
專案按右鍵 Properties產生 Web.xml
增加 jar 檔
※build.gradle
apply plugin: 'java-library' repositories { jcenter() } def springVer = '3.2.13.RELEASE' dependencies { api 'org.apache.commons:commons-math3:3.6.1' implementation 'com.google.guava:guava:21.0' testImplementation 'junit:junit:4.12' compile 'org.springframework:spring-context:"${springVer}"' compile group: 'org.springframework', name: 'spring-webmvc', version: "${springVer}" // compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2' compile group: 'javax.servlet', name: 'jstl', version: '1.2' }
※之後只要有改,就要在專案按右鍵做如下的設定,才會更新 build.gradle
※web.xml
<servlet> <servlet-name>testServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/testServlet-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>testServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
※根據官方文件的第二張圖 (Context hierarchy in Spring Web MVC) 下面,第一段有說明 [servlet-name]-servlet.xml in the WEB-INF,表示預設會在 WEB-INF 下找 [servlet-name]-servlet.xml,以此例來說就是 testServlet-servlet.xml,如果是叫這個名字且放在這個目錄下,那就可以不寫 init-param
※如果想用 annotation,本篇最下面有
※testServlet-servlet.xml
<context:component-scan base-package="controller" />
※
※XxxAction.java
@Controller public class XxxAction { @RequestMapping("/ooo/xxx/*.mvc") public String hello() { System.out.println("hello mvc"); return "/WEB-INF/hello.jsp"; } }
※只要是/ooo/xxx/開頭且是 mvc 結尾就會進來這個方法,進來後導向到另一支 jsp
※index.jsp
<a href="ooo/xxx/hello.mvc">Hello World</a>
※也可用 form,但網址是 GET,所以也可以用這個方式連後端
※@RequestMapping
可寫在類和方法上,兩個都寫可以合併,如上例可改成下面二種方式@Controller @RequestMapping("/ooo") public class XxxAction { @RequestMapping("/xxx/*.mvc") public String hello() { System.out.println("hello mvc"); return "/WEB-INF/hello.jsp"; } }
@Controller @RequestMapping("/ooo/xxx/") public class XxxAction { @RequestMapping("*.mvc") public String hello() { System.out.println("hello mvc"); return "/WEB-INF/hello.jsp"; } }
※處理 view
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- <property name="viewClass" --> <!-- value="org.springframework.web.servlet.view.JstlView" /> --> <property name="prefix" value="/WEB-INF/" /> <property name="suffix" value=".jsp" /> </bean>
※可在 testServlet-servlet.xml 增加這段,可參考官網
※JstlView 需要 JSTL 的 jar 包,但此例可以不加這個屬性,只要一加上,也不用寫上面那個 viewClass屬性,DispatcherServlet.resolveViewName,裡面的迴圈有個 View,會回傳 JstlView,原本是 InternalResourceView
因為 InternalResourceViewResolver 的預設建構子有寫
※上面的 gradle.build 有寫兩個,要小心註解那一個是有問題的,會出找不到 jstl 的 class
※設定好後,controller 只要回傳 hello 即可
※編譯及執行問題
編譯時找不到 Servlet,可在專案按右鍵 Build Path >> Configure Build Path >> Libraries 活頁標籤裡的 Add Library,然後如下操作運行時出現找不到 DispatcherServlet 的 class,可如下操作
※tomcat 還要打包到指定的路徑上,這裡不選 ,jar 包就不會包到指定的地方,此時就找不到jar 檔而報錯,所以只要將 gradle 下載的 jar 選起來即可
※@RequestMapping
※value 支援三種通配符:?、*、**※@RequestMapping(value = "*.mvc", method = RequestMethod.POST, params = { "xxx", "ooo=9" }, headers="Host=localhost:9080")
※params 表示一定要有屬性 xxx 和 ooo,且屬性 ooo一定要是 9 的,且 request header 的 Host 一定要是 localhost:9080 才可以請求,否則 404
※param 裡的都是字串,只能用「=」、「!=」,沒有正則表達式
※注意如果 params 過了,但 headers 沒通過,錯誤訊息還是顯示 params 沒通過
※瀏覽器可看到 header 的訊息,以 Chrome 為例
※@RequestParam、@RequestHeader、@CookieValue
@RequestMapping(value = "abc/*.mvc") public String hello( @RequestParam(value = "id", defaultValue = "0") int i, @RequestParam(value = "name", required = false) String n, @RequestHeader(value = "Accept-Language") String alang, @CookieValue("JSESSIONID") String cookie) { System.out.println(i + ":" + n + ":" + alang + ":" + cookie); return "hello"; }
※這三個 annotation 裡的屬性一樣,用法也差不多,也都只能寫在參數裡
※假設 hello(@RequestParam(value="id") int id),因為都叫 id,所以 annotation 可以不寫,主要是用在 defaultValue 和 required 這兩個屬性要設定時
※注意如果是基本型態,沒有 null,required 設定 false,還是會 400,可以改成 Wrapper 型態或者使用 defaultValue
※@RequestHeader 的 value 一樣是看上一張圖
※@CookieValue 的 value 看上一張圖的 Cookie
※測試
<a href="ooo/xxx/abc/bruce.mvc?id=99&name=bruce">param</a>
※
※@PathVariable
※只能寫在參數裡※
@RequestMapping("abc/{name}") public String pathVar(@PathVariable("name") String n) { System.out.println(n); return "hello"; }
※{name} 必需和 @PathVariable 裡的字對應
※
<a href="ooo/xxx/abc/bruce">param</a> <a href="ooo/xxx/abc/bruce.mvc">param</a>
※如果 web.xml 設定附檔名對應,就寫第二種;如果全部都給 spring 處理,就寫第一種,抓到的都是 bruce
※其他方式
※mvc:view-controller
假設 controller 沒做什麼事,只是重導而已,可以用這個,就不用寫 controller 了官網連結
※testServlet-servlet.xml
<mvc:view-controller path="ooo/xxx/view.mvc" view-name="hello" /> <mvc:annotation-driven />
※path 為請求的網址,和 @RequestMapping 不同,如果 web.xml 設定 *.mvc,在這裡一定要打才行,但 @RequestMapping 可打可不打
※view-name 會配合 InternalResourceViewResolver 設定的路徑
※annotation-driven 不寫時,ooo/xxx/view.mvc 這個請求沒有問題,但其他的,如上面有很多的其他請求會 404,加上這個才可以正常訪問
※如果這個設定和 controller 都寫了,會以 controller 為主
※重導
@RequestMapping("view") public String takeView() { System.out.println("yeah"); return "forward:/WEB-INF/hello.jsp"; //return "redirect:/success.html"; } ------------------------------ <a href="ooo/xxx/view.mvc">view</a>
※使用重導的方式,InternalResourceViewResolver 是沒有作用的
.直接請求重導 forward
A想拿東西給B,一進門看到C,C會轉交給B,有沒有轉交成功,A都會知道
伺服器端很忙,因為何服器會去找,所以可以找到WEB-INF之下的資源,所以網址不變
使用 RequestDispatcher
.間接請求重導 redirect
A想拿東西給B,一進門看到C,C叫他自己去找B
用戶端很忙,因為是用戶端,所以找不到WEB-INF之下的資源,所以網址會變
使用 HttpServletRequest,很明顯是用戶端
※不寫 web.xml
※@WebServlet( urlPatterns = "*.mvc", initParams = @WebInitParam( name = "contextConfigLocation", value = "/WEB-INF/applicationContext.xml" ) ) public class TestDispatcherServlet extends DispatcherServlet {}
※隨便寫個類實作 DispatcherServlet,然後如上代碼,注意 @WebInitParam 寫在 @WebServlet 裡面才有用
※如果不寫 @WebInitParam,那預設的 spring 設定檔名是「套件名.類名-servlet.xml」,此例為 init.TestDispatcherServlet-servlet.xml
※又如果不想用 applicationContext,直接使用 annotation,可如下設定
@WebServlet( urlPatterns = "/", initParams = { @WebInitParam(name = "contextConfigLocation", value = "controller.XxxAction"), @WebInitParam(name = "contextClass", value = "org.springframework.web.context.support.AnnotationConfigWebApplicationContext") }) public class TestDispatcherServlet extends DispatcherServlet {}
沒有留言:
張貼留言