知乎专栏 |
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"; } }
@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)
处理 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"]
@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
@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
查询接口
@GetMapping("keyword") public Optional<Lora> keywordTest(@RequestParam("key") Set<String> keyword) { Optional<Lora> lora = loraRepository.findByKeywordIn(keyword); return lora; }
GET 传递 Set 参数的方法如下
curl -X 'GET' \ 'http://localhost:8080/lora/keyword?key=aaa&key=bbb&key=ccc' \ -H 'accept: */*'
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); }
使用 required = false 标注参数是非必须的
@RequestParam(name = "age", required = false) Integer age
@PostMapping("/token") @ResponseBody public String token(@RequestParam Map<String, String> params) { log.debug(params.toString()); String token = jwtTokeComponent.getTestToken(params.get("appId"), params.get("appKey"), params.get("subject"), params.get("audience")); return token; }
@RequestParam(value = "secondary", required = false, defaultValue = "false") Boolean secondary
@PostMapping("create/premium") @TokenPass public AigcResponse pictureBookPremium(@RequestParam("title") String title, @RequestParam("backstory") String backstory, @RequestParam(value = "character", required = false) String character, @RequestParam(value = "sence", required = false) Integer sence, @RequestParam(value = "storyline", required = false) String storyline, @RequestParam(value = "style", required = false) String style, @RequestParam(value = "voice", required = false) String voice, @RequestParam(value = "secondary", required = false, defaultValue = "false") Boolean secondary ) { Optional<String> optional = pictureBookService.pictureBookPremium(title, backstory, character, sence, storyline, style, voice, secondary); return optional.map(AigcResponse::new).orElseGet(() -> new AigcResponse(null)); }
@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; }
/* 请求为/netkiller/color=123,321 那么color值为123,321 */ @RequestMapping(path="/netkiller/{id}", method=RequestMethod.GET) public String test1(@MatrixVariable Integer[] color){} /* 请求为/netkiller/color=123;color=321 那么color值为123,321 */ @RequestMapping(path="/netkiller/{id}", method=RequestMethod.GET) public String test1(@MatrixVariable Integer[] color){}
@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; } }