知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
package cn.netkiller.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class Welcome { @RequestMapping("/welcome") public ModelAndView helloWorld() { String message = "Helloworld!!!"; return new ModelAndView("welcome", "message", message); } }
@RequestMapping("/welcome")
@RequestMapping(value = "/list", method = RequestMethod.GET)
package com.cf88.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/") public class HelloController { @RequestMapping(value = "/{name}", method = RequestMethod.GET) public String getMovie(@PathVariable String name, ModelMap model) { model.addAttribute("name", name); return "hello"; } }
同時支持多種操作方法
@RequestMapping(value = "/name", method = { RequestMethod.GET, RequestMethod.POST })
@RequestMapping({ "/news/zh-cn", "/news/zh-tw" }) @ResponseBody public String getNewsByPath() { return "Hello"; }
@Controller @RequestMapping("/test/*") public class TestController { @RequestMapping public String default() { return "OK"; } }
@RequestMapping(value = "/news/json", method = GET, headers = "Accept=application/json") @ResponseBody public String getFoosAsJsonFromBrowser() { return "{...}"; }
curl -H "Accept:application/json,text/html" http://localhost:8080/spring/news/json.html
@GetMapping 等效與 @RequestMapping
@RequestMapping(value = "/news/list", method = GET)
範例
import org.springframework.web.bind.annotation.GetMapping; @GetMapping("/finance/list") public String financeList() { return financeService.financeList(); }
@GetMapping(value = "/user",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@GetMapping 等效與 @RequestMapping
@RequestMapping(value = "/news/list", method = RequestMethod.POST)
範例
import org.springframework.web.bind.annotation.PostMapping; @PostMapping("/finance/list") public String financeList() { return financeService.financeList(); }
Content-Type: multipart/form-data
@PostMapping(path = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@RequestParam 用來處理 HTTP GET/POST 請求的變數
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("/request/param") @ResponseBody public String getBarBySimplePathWithRequestParam(@RequestParam("id") long id) { return "Get a specific Bar with id=" + id; }
http://localhost:8080/Spring/request/param.html?id=100
package cn.netkiller.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; @Controller public class Http { @RequestMapping("/http/form") public ModelAndView createCustomer(){ ModelMap model = new ModelMap(); model.addAttribute("email", "netkiller@msn.com"); model.addAttribute("phone", "13113668890"); return new ModelAndView("http/form", model); } @RequestMapping(value= "/http/post", method = RequestMethod.POST) public ModelAndView saveCustomer(HttpServletRequest request, @RequestParam(value="Email", required=false) String email, @RequestParam(value="Password", required=false) String password, @RequestParam(value="Phone", required=false) String phone){ ModelMap model = new ModelMap(); model.addAttribute("email", email); model.addAttribute("password", password); model.addAttribute("phone", phone); return new ModelAndView("http/post", model); } }
http/form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form method="POST" action="http://localhost:8080/Spring/http/post.html" id="Register" name="Register"> Email: <input class="register" type="text" id="Email" name="Email" value="${email}" /> <br /> Password: <input class="register" type="password" id="Password" name="Password" value="" /><br /> Phone: <input class="register" type="text" id="Phone" name="Phone" value="${phone}" /> <br /> <input type="submit" id="btnRegister" name="btnRegister" value="Register" style="cursor: pointer" /> </form> </body> </html>
http/post.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${email}<br> ${password} <br> ${phone} <br> </body> </html>
URL 中 “+” 有特殊意義,表示空格。
如果 @RequestParam 傳遞參數含有空格可以這樣處理。
@RequestMapping("/RequestParam") @ResponseBody public String query(@RequestParam("code") String code) { return code.replace(" ", "+"); }
@RequestMapping("/range") public ModelAndView range(@RequestParam("beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate, @RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) { log.info("===== Begin ===== {}", beginDate); // 你的邏輯 log.info("===== End ===== {}", endDate); return new ModelAndView("activity/index", "message", "操作成功"); }
package cn.netkiller.restful; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/upload") public class UploadRestController { private static final Logger logger = LoggerFactory.getLogger(UploadRestController.class); public UploadRestController() { // TODO Auto-generated constructor stub } @PostMapping("/add") public String fileUpload(@RequestParam("file") MultipartFile multipartFile) throws IOException { String name = multipartFile.getOriginalFilename(); System.out.println("File name: " + name); // todo save to a file via multipartFile.getInputStream() byte[] bytes = multipartFile.getBytes(); System.out.println("File uploaded content:\n" + new String(bytes)); return "file uploaded"; } }
操作演示,首先創建一個檔案
echo "Helloworld!!!" > hello.txt
上傳該檔案
neo@MacBook-Pro /tmp % curl "http://localhost:8080/upload/add" \ -X POST \ -H "Content-Type: multipart/form-data" \ -F file=@"hello.txt" file uploaded
HTTP 頭
picture[]: gather/293a93baa02cb18a840631bac1f9eeb20b7d436f.jpeg picture[]: gather/be7572e4df527b4389d605766ea65aafcf2d822a.jpg
@PostMapping("/save") public String save(@RequestParam(value = "picture[]", required = true) String[] picture) { return String.join(",", picture); }
處理 raw 原始數據,例如提交的時 application/json, application/xml等
@RequestMapping(value = "/something", method = RequestMethod.PUT) public void handle(@RequestBody String body, Writer writer) throws IOException { writer.write(body); }
package cn.netkiller.api.restful; import java.util.List; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class TestRestController { @RequestMapping(value = "/test/list/{siteId}", method = RequestMethod.POST) public List<String> ping(@PathVariable("siteId") int siteId, @RequestBody List<String> tags) { System.out.println(String.format("%d, %s", siteId, tags)); return (tags); } }
$ curl -H "Content-Type: application/json" -X POST -d '["Neo","Netkiller"]' http://localhost:8440/test/list/22.json ["Neo","Netkiller"]
@RequestMapping("/displayHeaderInfo") public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) { //... }
獲取用戶當前語言
@GetMapping("/lang") public String language(@RequestHeader("Accept-Language") String locale ) { System.out.println(locale); return locale; }
下面代碼可以獲得相同效果
@GetMapping("/lang") public String language(Locale locale) { System.out.println(locale); return locale; } @GetMapping("/lang") public String language() { String locale = LocaleContextHolder.getLocale().toString(); System.out.println(locale); return locale; }
PATHINFO 變數可通過 @Pathvariable註解綁定它傳過來的值到方法的參數上。
需求,我們需要通過URL傳遞參數,所傳遞的值是分類ID與文章ID,例如 /news/1.html, /news/1/1.html。
package cn.netkiller.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class Pathinfo { @RequestMapping("/pathinfo/{id}") public ModelAndView urlTestId(@PathVariable String id) { return new ModelAndView("pathinfo/param", "id", id); } @RequestMapping("/pathinfo/{cid}/{id}") public ModelAndView urlTestId(@PathVariable String cid, @PathVariable String id) { ModelMap model = new ModelMap(); model.addAttribute("cid", cid); model.addAttribute("id", id); return new ModelAndView("pathinfo/param", model); } }
jsp測試檔案
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${ cid } <br> ${ id } <br> </body> </html>
required 設置參數不是必須的
@PathVariable(required = false) String id
設置多個映射
@RequestMapping(value = {"/organization/{pageNumber}", "/organization"} , method = RequestMethod.GET) public String list(@PathVariable(required = false) Integer pageNumber, ModelMap modelMap){ ... }
http://localhost:7000/history/2016-09-28%2000:00:00/
@RequestMapping("/history/{datetime}") public String history(@PathVariable @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date datetime) throws Exception { System.out.println(datetime) return null; }
http://www.netkiller.cn/release/1.0.1
@RequestMapping(value = "/release/{version:[a-zA-Z0-9\\.]+}", method = RequestMethod.GET) public @ResponseBody String release(@PathVariable String version) { log.debug("version: ", version); return version; }
http://www.netkiller.cn/release/1.0.1/other
@RequestMapping(value="/release/{version:.+}",method=RequestMethod.GET) public void download(HttpSession session,@PathVariable("version")String version){ return version; }
@ModelAttribute 處理 HTML FORM POST 提交
package cn.netkiller.pojo; import java.util.List; public class Deploy { private String group; private String envionment; private String project; private List<String> arguments; public Deploy() { // TODO Auto-generated constructor stub } // Getters & Setters }
@RequestMapping(value="/deploy/post", method = RequestMethod.POST) public ModelAndView post(@ModelAttribute("deploy")Deploy deploy, BindingResult result) { if (result.hasErrors()) { System.out.println(result.toString()); } System.out.println(deploy.toString()); return new ModelAndView("output").addObject("output", deploy.toString()); }
import org.springframework.web.bind.annotation.ResponseBody;
package cn.netkiller.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; @Controller public class Pathinfo { @RequestMapping(value = "/news/shenzhen/{numericId:[\\d]+}") @ResponseBody public String getNewsWithPathVariable(@PathVariable final long numericId) { return "Get a specific Bar with id=" + numericId; } }
@RequestMapping(value = "/", method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) public String create(@RequestBody MultiValueMap<String, String> map) { return "OK"; }
@CrossOrigin(origins = "http://localhost:9000") @GetMapping("/greeting") public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) { System.out.println("==== in greeting ===="); return new Greeting(counter.incrementAndGet(), String.format(template,name)); }
@CrossOrigin(origins = "*", allowedHeaders = "*") @RestController public class HomeController { @GetMapping(path="/") public String home() { return "home"; } }
全局放行所有輕鬆,方法權限單獨控制
@RestController @CrossOrigin(origins = "*", allowedHeaders = "*") public class HomeController { @CrossOrigin(origins = "http://example.com") @GetMapping(path="/") public String home() { return "home"; } }
@CrossOrigin(origins = {"http://localhost:8585"}, maxAge = 4800, allowCredentials = "false") @RestController @RequestMapping("/info") public class PersonController { @Autowired private PersonService service; @CrossOrigin(origins = {"http://localhost:8080"}, maxAge = 6000) @RequestMapping("home") public List<Person> show() { List<Person> list = service.getAllPerson(); return list; } }
@RequestMapping("/sessionInfo") public void sessionInfo(@CookieValue("JSESSIONID") String cookie) { //... }
@SessionAttributes: 該註解用來綁定HttpSession中的attribute對象的值,便于在方法中的參數里使用。 該註解有value、types兩個屬性,可以通過名字和類型指定要使用的attribute 對象;
@Controller @RequestMapping("/editProfile") @SessionAttributes("profile") public class ProfileForm { // ... }
@Controller @SessionAttributes("myRequestObject") public class MyController { ... }
@RequestMapping("/testString") public ModelAndView helloWorld() { String message = "Helloworld!!!"; return new ModelAndView("welcome", "message", message); }
public ModelAndView handleRequestInternal() { ModelAndView mav = new ModelAndView("test");// 實例化一個VIew的ModelAndView實例 mav.addObject("variable", "Hello World!");// 添加一個帶名的model對象 return mav; }
傳遞多個字元串
@RequestMapping("/testModelMap") public ModelAndView testModelMap() { ModelMap model = new ModelMap(); model.addAttribute("username", "Neo"); model.addAttribute("password", "Netkiller"); return new ModelAndView("test/modelmap", model); }
推薦使用ModelMap
@RequestMapping("/testMapString") public ModelAndView testMapString() { Map<String,String> data = new HashMap<String,String>(); data.put("username","Neo"); data.put("password","Netkiller"); return new ModelAndView("test/modelmap",data); }
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> ${username}<br> ${password}<br> </body> </html>
@RequestMapping("/testRedirect") public ModelAndView testRedirect(){ RedirectView view = new RedirectView("testMapString.html"); return new ModelAndView(view); }
@RequestMapping(value = "testList") public ModelAndView testList() { ModelAndView mav = new ModelAndView(); mav.setViewName("/test/list"); // List List<String> list = new ArrayList<String>(); list.add("java"); list.add("c++"); list.add("oracle"); mav.addObject("bookList", list); return mav; }
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> ${bookList} <br> <c:forEach items="${bookList}" var="node"> <c:out value="${node}"></c:out><br> </c:forEach> </body> </html>
@RequestMapping("/testMap") public ModelAndView testMap() { ModelAndView mav = new ModelAndView(); mav.setViewName("test/map"); // 返回的檔案名 // Map Map<String, String> map = new HashMap<String, String>(); map.put("Java", "http://www.netkiller.cn/java"); map.put("PHP", "http://www.netkiller.cn/php"); map.put("Home", "http://www.netkiller.cn"); mav.addObject("channel", map); return mav; }
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <c:forEach items="${channel}" var="node"> <a href="<c:out value="${node.value}"></c:out>"><c:out value="${node.key}"></c:out></a> <br/> </c:forEach> </body> </html>
@RequestMapping("/testObject") public ModelAndView testObject() { ModelMap model = new ModelMap(); User user = new User("neo", "passw0rd"); model.addAttribute("user", user); return new ModelAndView("test/object", model); }
package cn.netkiller; public class User { public String username; public String password; public User(String username, String password){ this.username = username; this.password = password; } public String getUsername(){ return this.username; } public String getPassword(){ return this.password; } }
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> Username: ${user.username}<br> Password: ${user.password}<br> </body> </html>
HttpServletResponse 實例
package cn.netkiller.api.rest; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import api.util.MatrixToImageWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Hashtable; @Controller @RequestMapping("/public/QRCode") public class QRCodeController { private static final Logger log = LoggerFactory.getLogger(QRCodeController.class); @RequestMapping("/create/{code}" ) @ResponseBody public void create(@PathVariable String code, HttpServletResponse httpServletResponse) throws WriterException, IOException { log.info(code); if (code != null && !"".equals(code)){ ServletOutputStream stream = null; try { String text = code; // 二維碼內容 int width = 300; // 二維碼圖片寬度 int height = 300; // 二維碼圖片高度 String format = "gif"; // 二維碼的圖片格式 Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 內容所使用字符集編碼 BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints); // 生成二維碼 stream = httpServletResponse.getOutputStream(); MatrixToImageWriter.writeToStream(bitMatrix, format, stream); }catch (WriterException e) { e.printStackTrace(); } finally { if (stream != null) { stream.flush(); stream.close(); } } } } @RequestMapping("show") @ResponseBody public ModelAndView show(){ return new ModelAndView("/qrcode/qrcode"); } }
package com.example.demo.controller; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/test") public class TestController { public TestController() { // TODO Auto-generated constructor stub } @GetMapping("/get") public String get(@RequestHeader String lang) throws IOException { System.out.println(lang); return lang; } @PostMapping("/post") public String post(@RequestHeader String lang) throws IOException { System.out.println(lang); return lang; } @GetMapping("/list") public Map<String, String> x(HttpServletRequest request) throws IOException { return getHeadersInfo(request); } private Map<String, String> getHeadersInfo(HttpServletRequest request) { Map<String, String> map = new HashMap<String, String>(); Enumeration<?> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = (String) headerNames.nextElement(); String value = request.getHeader(key); map.put(key, value); } return map; } }