定义映射关系
@Controller
定义控制器的一个类
@RequestMapping
- path / method 指定url映射路径与对应http方法
- params / headers 限定映射范围,带有什么参数或不带什么参数能映射过来,http头里面带什么头或者不带什么头
- consumes / produces 限定请求与响应格式,我处理的请求当中包含特定信息的请求;这个请求它只会参生特定形式
一些快捷方式
- @RestController
相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面 - @GetMapping / @PostMapping / @PutMapping / @DeleteMapping / @PatchMapping
get请求。post请求等等
定义处理方法
- @RequestBody / @ResponseBody / @ResponseStatus
请求的正文、响应正文、返回响应的http状态码 - @PathVariable / @RequestParam / @RequestHeader
URL上的路径里面的变量,请求的参数,请求的http的头 - HttpEntity / ResponseEntity
配置
例子
@Controller
@RequestMapping("/coffee")
public class CoffeeController {
@Autowired
private CoffeeService coffeeService;
@GetMapping(path = "/", params = "!name") //如果后面跟的不是名字,为查全部的
@ResponseBody
public List<Coffee> getAll() {
return coffeeService.getAllCoffee();
}
@RequestMapping(path = "/{id}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) //根据id查
@ResponseBody
public Coffee getById(@PathVariable Long id) { //通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
Coffee coffee = coffeeService.getCoffee(id);
return coffee;
}
@GetMapping(path = "/", params = "name") //根据name查
@ResponseBody
public Coffee getByName(@RequestParam String name) {
return coffeeService.getCoffee(name);
} //@RequestParam从请求中提取查询参数,表单参数甚至文件
}
@RestController
@RequestMapping("/order")
@Slf4j
public class CoffeeOrderController {
@Autowired
private CoffeeOrderService orderService;
@Autowired
private CoffeeService coffeeService;
@GetMapping("/{id}")//根据id取订单
public CoffeeOrder getOrder(@PathVariable("id") Long id) {
return orderService.get(id);
}
@PostMapping(path = "/", consumes = MediaType.APPLICATION_JSON_VALUE, //Content-Type类型为application/json
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) //Accept类型为application/json;charset=UTF-8
@ResponseStatus(HttpStatus.CREATED) //http响应码为201创建码
public CoffeeOrder create(@RequestBody NewOrderRequest newOrder) {
log.info("Receive new Order {}", newOrder);
Coffee[] coffeeList = coffeeService.getCoffeeByName(newOrder.getItems())
.toArray(new Coffee[] {});
return orderService.createOrder(newOrder.getCustomer(), coffeeList);
}
}
结果如下:
根据id查咖啡:
查询所有咖啡:
根据name查:
创建订单:
创建成功之后,返回的是201http状态码;同时,Content-Type与Accept的格式不能少,否则保存。因为,在代码中已经指定过了。
根据id获取订单:
定义类型转换
在springboot中,我们需要自己实现 WebMvcConfigurer,在springboot中已经实现了 WebMvcAutoConfiguration,所有就需要我们去添加一个自定义的Converter/Formatter
定义校验
通过 Validator 对绑定结果进行校验,比如说使用Hibernate Validator
在绑定的对象上面添加一个@Valid 注解,springmvc会帮我做Validator
检查的结果通过BindingResult传入进来
Multipart(文件) 上传
配置 MultipartResolver
• Spring Boot 自动配置 MultipartAutoConfiguration
支持类型 multipart/form-data的上传,上传的是一个MultipartFile 类型
扫描二维码关注公众号,回复:
8754217 查看本文章
例子
我们在代码中新添加了一些类,目录如下:
@Component//带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化。其他类级别的注解也可以被认定为是一种特殊类型的组件
public class MoneyFormatter implements Formatter<Money> {
/**
* 处理 CNY 10.00 / 10.00 形式的字符串
* 校验不太严密,仅作演示
*/
@Override
public Money parse(String text, Locale locale) throws ParseException { //从文本到money的转换
if (NumberUtils.isParsable(text)) { //判断是否为数字
return Money.of(CurrencyUnit.of("CNY"), NumberUtils.createBigDecimal(text));
} else if (StringUtils.isNotEmpty(text)) {//判断是否为空
String[] split = StringUtils.split(text, " ");//根据空格截取
if (split != null && split.length == 2 && NumberUtils.isParsable(split[1])) {
return Money.of(CurrencyUnit.of(split[0]), //取出类型
NumberUtils.createBigDecimal(split[1])); //取出金额并处理
} else {
throw new ParseException(text, 0);
}
}
throw new ParseException(text, 0);
}
@Override
public String print(Money money, Locale locale) { //输出money
if (money == null) {
return null;
}
return money.getCurrencyUnit().getCode() + " " + money.getAmount();
}
}
@Getter
@Setter
@ToString
public class NewCoffeeRequest {
@NotEmpty
private String name;
@NotNull
private Money price;
//这些属性表单不填的话 会导致提交失败
}
@Controller
@RequestMapping("/coffee")
@Slf4j
public class CoffeeController {
@Autowired
private CoffeeService coffeeService;
@PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public Coffee addCoffee(@Valid NewCoffeeRequest newCoffee,
BindingResult result) {
if (result.hasErrors()) {
// 这里先简单处理一下,后续讲到异常处理时会改
log.warn("Binding Errors: {}", result);
return null;
}
return coffeeService.saveCoffee(newCoffee.getName(), newCoffee.getPrice());
}
//@PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) //表单的演示
//@ResponseBody
//@ResponseStatus(HttpStatus.CREATED)
//public Coffee addCoffeeWithoutBindingResult(@Valid NewCoffeeRequest newCoffee) { //@Valid表单绑定之后 做一个校验value是否合法
// return coffeeService.saveCoffee(newCoffee.getName(), newCoffee.getPrice());
//}
@PostMapping(path = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public List<Coffee> batchAddCoffee(@RequestParam("file") MultipartFile file) {
List<Coffee> coffees = new ArrayList<>();
if (!file.isEmpty()) {
BufferedReader reader = null;
try {
reader = new BufferedReader(
new InputStreamReader(file.getInputStream()));
String str;
while ((str = reader.readLine()) != null) {
String[] arr = StringUtils.split(str, " ");//咖啡名字和金额
if (arr != null && arr.length == 2) {
coffees.add(coffeeService.saveCoffee(arr[0],
Money.of(CurrencyUnit.of("CNY"),
NumberUtils.createBigDecimal(arr[1]))));
}
}
} catch (IOException e) {
log.error("exception", e);
} finally {
IOUtils.closeQuietly(reader);
}
}
return coffees;
}
@GetMapping(path = "/", params = "!name")
@ResponseBody
public List<Coffee> getAll() {
return coffeeService.getAllCoffee();
}
@RequestMapping(path = "/{id}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Coffee getById(@PathVariable Long id) {
Coffee coffee = coffeeService.getCoffee(id);
return coffee;
}
@GetMapping(path = "/", params = "name")
@ResponseBody
public Coffee getByName(@RequestParam String name) {
return coffeeService.getCoffee(name);
}
}
使用addCoffeeWithoutBindingResult方法添加咖啡:
当然,如何输入value不合法,就会导致报错。如果我们不希望springmvc去处理错误,我们可以自己去处理。我们打开addCoffee注解。
如图所示,我们自己处理了之后,返回了一个null
控制台输出错误信息:
使用文件上传创建咖啡: