一個最基本的Spring Controller就是一個類別,首先,會定義package,請養成習慣把controller都放在controller的package裡,並定義所需要import的類別,接下來,會利用java的Annotation:「@」來定義這個類別是個Controller。在類別中,指定home這個方法的RequestMapping (詳參: http://peaceful-developer.blogspot.tw/2014/08/spring-2-requestmapping.html),也就是指定這個Controller的相對URI,以下面的範例,就是告訴web server,當瀏覽器要求"/"時,就呼叫home()。另外,@ResponseBody會將home()的回傳值當做是Response的內容。也就是網頁上會看到「Hello World」。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class SampleController { @RequestMapping("/") @ResponseBody public String home() { return "Hello World"; }}如 果不使用@ResponseBody的話,return值就變成要重導的網頁名稱了。如:
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class SampleController { @RequestMapping("/") public String home() { return "index.html"; }}Controller可以跟View互動,我們先介紹如何傳值到View。第一種方式是使用Model,Model提供addAttribute(),第一個參數是傳到view之後,對應變數的名稱,第二個參數是傳過去的內容,下面的範例就是將變數名稱「name」內容為「ben」傳到hello。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.ui.Model;@Controllerpublic class HelloController { @RequestMapping("/hello") public String home(Model model) { model.addAttribute("name", "ben"); return "hi"; }}第二種方式是使用ModelAndView,在產生ModelAndView時,可以指定hi為呼叫的view。ModelAndView提供addObject(),第一個參數是傳到view之後,對應變數的名稱,第二個參數是傳過去的內容,下面的範例就是將變數名稱「name」內容為「ben」傳到hi。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController { @RequestMapping("/hello") public ModelAndView home() { ModelAndView model = new ModelAndView("hello"); model.addObject("name", "ben"); return model; }}對應的hello.html (採用Thymeleaf)內容如下:
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Hello!</title></head><body><h2>Hello! <span th:text="${name}">Wu</span></h2> </body></html>如果是物件的話,是以addObject的第一個參數(如:newcustomer)做為傳遞的對應名稱,而不是使用變數名稱(如:cus)。
@RequestMapping(value = "/customerUpdate", method = RequestMethod.GET) public ModelAndView openFormUpdate(@RequestParam(value="id", required=false, defaultValue="1") Long id) { ModelAndView model = new ModelAndView("customerUpdate"); Customer cus = dao.findOne(id); model.addObject("newcustomer",cus); return model; }對應的view(customerUpdate.html):
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Update Customer</title></head><body><form action="customerUpdate" th:object="${newcustomer}" method ="post"> name:<input type="text" name="name" th:field="*{name}"/><br/> address:<input type="text" name = "address" th:field="*{address}"/><br/> weight:<input type="text" name ="weight" th:field="*{weight}"/><br/> <input type="hidden" name ="id" th:field="*{id}"/> <input type="submit" value="Submit"/></form></body></html>如果controller中的addObject是用物件傳送資料(單一參數),在Thymeleaf中,會以物件的類別名稱(如:Customer)來做為物件的名稱, 不過,會將第一個字母的大寫轉為小寫(如:customer),而不是使用變數名稱(如:cus)
@RequestMapping(value = "/customerUpdate", method = RequestMethod.GET) public ModelAndView openFormUpdate(@RequestParam(value="id", required=false, defaultValue="1") Long id) { ModelAndView model = new ModelAndView("customerUpdate"); Customer cus = dao.findOne(id); model.addObject(cus); return model; }對應的view(customerUpdate.html):
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Update Customer</title></head><body><form action="customerUpdate" th:object="${customer}" method ="post"> name:<input type="text" name="name" th:field="*{name}"/><br/> address:<input type="text" name = "address" th:field="*{address}"/><br/> weight:<input type="text" name ="weight" th:field="*{weight}"/><br/> <input type="hidden" name ="id" th:field="*{id}"/> <input type="submit" value="Submit"/></form></body></html>接收參數的方法有好幾種,第一種方式是利用HttpServletRequest,利用getParameter來存取對應的變數。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;@Controllerpublic class HelloController { @RequestMapping("/helloWithId") public ModelAndView home(HttpServletRequest request) { ModelAndView model = new ModelAndView("hi"); String name = request.getParameter("id"); model.addObject("name", name); return model; }}第二種方式是利用@RequestParam,可以設定這個參數不是必要的,也可以設定當參數不存在時的預設值。這樣程式碼簡潔多了。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController { @RequestMapping("/helloWithId") public ModelAndView home(@RequestParam(value="id", required=false, defaultValue="world") String name) { ModelAndView model = new ModelAndView("hi"); model.addObject("name", name); return model; }}第三種方式是利用@ModelAttribute。這樣程式碼簡潔多了。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController { @RequestMapping("/helloWithId") public ModelAndView home(@ModelAttribute("id") String name) { ModelAndView model = new ModelAndView("hi"); model.addObject("name", name); return model; }}使用@ModelAttribute的另一個好處是可以接受一個物件。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;import com.example.demo.entity.Customer;@Controllerpublic class CustomerController { @RequestMapping(value = "/customerCreate", method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("customerCreate"); return model; } @RequestMapping(value = "/customerCreate", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute Customer cus) { ModelAndView model = new ModelAndView("customerDone"); model.addObject("customer",cus); return model; } }上面的範例在RequestMapping中,除了指定URI之外,還指定了RequestMethod,這樣就可以兩個方法(openForm, processForm)使用同一個URI (細節請參閱後面對於RequestMapping的說明)。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;import com.example.demo.entity.Customer;@Controllerpublic class CustomerController { @RequestMapping(value = "/customerCreate", method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("customerCreate"); return model; } @RequestMapping(value = "/customerCreate", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute Customer cus) { ModelAndView model = new ModelAndView("customerDone"); model.addObject("customer",cus); return model; } }必須配合Customer.java,這樣的類別就屬於Model,其內容如下:
package com.example.demo.entity;public class Customer { private String name; private String address; private int weight; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; }}以及customerCreate.html
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body><form action="customerCreate" method ="post"> name:<input type="text" name="name"/><br/> address:<input type="text" name = "address"/><br/> weight:<input type="text" name ="weight"/><br/> <input type="submit" value="Submit"/></form></body></html>及customerDone.html。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body>name: <span th:text="${customer.name}">Wu</span>address: <span th:text="${customer.address}">Fu Jen</span>weight: <span th:text="${customer.weight}">56</span></body></html>另外,利用model.addObject時,是利用第一個參數(如:newcustomer)來指定view的接收變數名稱。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;import com.example.demo.entity.Customer;@Controllerpublic class CustomerController { @RequestMapping(value = "/customerCreate", method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("customerCreate"); return model; } @RequestMapping(value = "/customerCreate", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute Customer cus) { ModelAndView model = new ModelAndView("customerDone"); model.addObject("newcustomer",cus); return model; } }對應的view (customerDone.html)。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body>name: <span th:text="${newcustomer.name}">Wu</span>address: <span th:text="${newcustomer.address}">Fu Jen</span>weight: <span th:text="${newcustomer.weight}">56</span></body></html>另外,如果省略第一個參數,在Thymeleaf中,會以物件的類別名稱(如:Customer)來做為物件的名稱, 不過,會將第一個字母的大寫轉為小寫(如:customer),而不是以變數名稱(如:cus)。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;import com.example.demo.entity.Customer;@Controllerpublic class CustomerController { @RequestMapping(value = "/customerCreate", method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("customerCreate"); return model; } @RequestMapping(value = "/customerCreate", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute Customer cus) { ModelAndView model = new ModelAndView("customerDone"); model.addObject(cus); return model; } }對應的view (customerDone.html)。
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Create New Customer</title></head><body>name: <span th:text="${customer.name}">Wu</span>address: <span th:text="${customer.address}">Fu Jen</span>weight: <span th:text="${customer.weight}">56</span></body></html>HTTP Request分為get與post,所以,同一個URI可以對應get及post。以下面的範例而言,呼叫GET時,打開hi.html,hi.html會呼叫POST,並傳送id給controller,controller將id內容存在name,傳回給hello.html。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController { @RequestMapping(value = "/helloWithId", method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("hi"); return model; } @RequestMapping(value = "/helloWithId", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute("id") String name) { ModelAndView model = new ModelAndView("hello"); model.addObject("name", name); return model; }}hi.html
<!DOCTYPE html><html><body><form action="helloWithId" method ="post"> id:<input type="text" name ="id"/><br> <input type="submit" value="Submit"/></form></body></html>hello.html (採用Thymeleaf)
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"/> <title>Hello!</title></head><body><h2>Hello! <span th:text="${name}">Wu</span></h2> </body></html>同一個方法可以對應多個uri,如:value = {"/helloWithId", "hello2"}。
package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController { @RequestMapping(value = {"/helloWithId", "/hello2"}, method = RequestMethod.GET) public ModelAndView openForm() { ModelAndView model = new ModelAndView("hi"); return model; } @RequestMapping(value = "/helloWithId", method = RequestMethod.POST) public ModelAndView processForm(@ModelAttribute("id") String name) { ModelAndView model = new ModelAndView("hello"); model.addObject("name", name); return model; }}