课程内容来自极客时间玩转Spring全家桶,侵私删,链接如下
https://time.geekbang.org/course/intro/100023501
第六章
如何定义Controller及其方法
定义映射关系
注解
@Controller
@RequestMapping
可以指定参数path/value 是等价的;
还可以指定method、params;params中不存在params的写法:!name 或者name=“zhangsan”;
headers同理(header=“content-type=text/*”);
consumes,可以是一个也可以多个;
produces对应的是accept头,也可以匹配多个,带!
参数具体详解可以看这文章
https://blog.csdn.net/weixin_43453386/article/details/83419060
@RestController
code
package geektime.spring.springbucks.waiter.controller;
import ...
@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)
@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);
}
}
package geektime.spring.springbucks.waiter.controller;
import ...
@RestController
@RequestMapping("/order")
@Slf4j
public class CoffeeOrderController {
@Autowired
private CoffeeOrderService orderService;
@Autowired
private CoffeeService coffeeService;
@GetMapping("/{id}")
public CoffeeOrder getOrder(@PathVariable("id") Long id) {
return orderService.get(id);
}
@PostMapping(path = "/", consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseStatus(HttpStatus.CREATED)
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);
}
}
使用postman,发送post请求,可以看到正常返回值
当post的类型不正确时,会返回415错误码
当post的Accept不正确时,会返回406错误码,服务器无法接受
请求自定义转换
配置过程
code
MoneyFormatter
package geektime.spring.springbucks.waiter.support;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.format.Formatter;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.util.Locale;
@Component
public class MoneyFormatter implements Formatter<Money> {
/**
* 处理 CNY 10.00 / 10.00 形式的字符串
* 校验不太严密,仅作演示
*/
@Override
public Money parse(String text, Locale locale) throws ParseException {
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) {
if (money == null) {
return null;
}
return money.getCurrencyUnit().getCode() + " " + money.getAmount();
}
}
方法体伪代码
@PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public Coffee addCoffeeWithoutBindingResult(@Valid NewCoffeeRequest newCoffee) {
return coffeeService.saveCoffee(newCoffee.getName(), newCoffee.getPrice());
}
如图,正确的格式
当post方法,所应带的值为空时,会报400bad request错误
当post方法,所带的price值,不能转换成数字时
思考练习
通过配置formatter进行金额处理于转换,但是当转换失败时,就由Spring返回bad request,如果不想直接返回,而中间需要夹杂处理及exception怎么办?
@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());
}