Spring MVC 有两种启动模式,一种是传统Tomcat,需要配置很多XML文件。另一种方式是采用 Spring Boot 需要些一个Java程序,不需要写xml文件,这个程序会帮助你处理启动所需的一切,并且采用嵌入方式启动 Tomcat 或者 Jetty.
两种方式各有优缺点,Tomcat 方式配置繁琐,但是可以使用虚拟机,同一个IP地址使用不同域名访问,出现不同的内容。而Spring Boot一个应用一个容器一个端口,比不得不通过端口来区分应用。
3.1. @Controller
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); } }
3.1.1. @RequestMapping
@RequestMapping("/welcome")
@RequestMapping(value = "/list", method = RequestMethod.GET)
3.1.1.1. @RequestMapping("/")
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"; } }
3.1.1.2. 映射多个URL
@RequestMapping({ "/news/zh-cn", "/news/zh-tw" }) @ResponseBody public String getNewsByPath() { return "Hello"; }
3.1.1.3. headers
@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
3.1.1.4. @GetMapping
@GetMapping 等效与 @RequestMapping
@RequestMapping(value = "/news/list", method = GET)
范例
import org.springframework.web.bind.annotation.GetMapping; @GetMapping("/finance/list") public String financeList() { return financeService.financeList(); }
3.1.1.5. @PostMapping
@GetMapping 等效与 @RequestMapping
@RequestMapping(value = "/news/list", method = method = RequestMethod.POST)
范例
import org.springframework.web.bind.annotation.PostMapping; @PostMapping("/finance/list") public String financeList() { return financeService.financeList(); }
3.1.2. RequestMapping with Path Variables - @PathVariable
PATHINFO 变量可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。
3.1.2.1. URL 参数传递
需求,我们需要通过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>
3.1.2.2. URL 传递 Date 类型
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; }
3.1.2.3. 处理特殊字符
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; }
3.1.2.4. @PathVariable 注意事项
@PathVariable 参数传统需要注意,参数中不能携带 “/”,斜杠会被视为目录。
@RequestMapping("/PathVariable/{code}.html") @ResponseBody public String urlTestId(@PathVariable String code) { return code; }
3.1.3. RequestMapping with Request Parameters - @RequestParam
@RequestParam 用来处理 HTTP GET/POST 请求的变量
import org.springframework.web.bind.annotation.RequestParam;
3.1.3.1. HTTP GET
@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
3.1.3.2. HTTP POST
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>
3.1.3.3. @RequestParam 传递特殊字符串
URL 中 “+” 有特殊意义,表示空格。
如果 @RequestParam 传递参数含有空格可以这样处理。
@RequestMapping("/RequestParam") @ResponseBody public String query(@RequestParam("code") String code) { return code.replace(" ", "+"); }
3.1.3.4. 传递日期参数
@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", "操作成功"); }
3.1.4. @RequestBody
处理 raw 原始数据,例如提交的时 application/json, application/xml等
@RequestMapping(value = "/something", method = RequestMethod.PUT) public void handle(@RequestBody String body, Writer writer) throws IOException { writer.write(body); }
3.1.4.1. @RequestBody 传递 List
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"]
3.1.4.2. 传递 Map 数据
@PostMapping("/finance/list") public String financeList(@RequestBody Map<String,String> map) { return financeService.financeList(map); }
% curl -H "Content-Type: application/json" -X POST -d '{"date":"2017-11-08"}' http://localhost:8440/finance/list.json
3.1.5. @ModelAttribute
@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()); }
3.1.6. @CookieValue
@RequestMapping("/sessionInfo") public void sessionInfo(@CookieValue("JSESSIONID") String cookie) { //... }
3.1.7. @RequestHeader
@RequestMapping("/displayHeaderInfo") public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) { //... }
3.1.8. @@SessionAttributes
@SessionAttributes: 该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。 该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;
@Controller @RequestMapping("/editProfile") @SessionAttributes("profile") public class ProfileForm { // ... }
3.1.9. @ResponseBody
import org.springframework.web.bind.annotation.ResponseBody;
3.1.9.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.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; } }
3.1.10. ModelAndView
3.1.10.1. 变量传递
@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; }
3.1.10.2. ModelMap 传递多个变量
传递多个字符串
@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>
3.1.10.3. redirect
@RequestMapping("/testRedirect") public ModelAndView testRedirect(){ RedirectView view = new RedirectView("testMapString.html"); return new ModelAndView(view); }
3.1.10.4. ArrayList
@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>
3.1.10.5. HashMap
@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>
3.1.10.6. 传递对象
@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>
3.1.10.7.
3.1.11. @CrossOrigin
@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)); }
3.1.12. @SessionAttributes
@Controller @SessionAttributes("myRequestObject") public class MyController { ... }
3.1.13. HttpServletRequest / HttpServletResponse
3.1.13.1. 用于方法参数
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"); } }
3.1.13.2. 注入方式
原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。