Spring Boot 中的静态资源配置
核心逻辑
• WebMvcConfigurer.addResourceHandlers()
常用配置
• spring.mvc.static-path-pattern=/**
静态资源的路径,默认的是从根路径开始匹配
• spring.resources.static-locations=classpath:/META-INF/ resources/,classpath:/resources/,classpath:/static/,classpath:/public/
springmvc 如何去寻找这些静态资源,在classpath的位置是怎么样的
Spring Boot 中的缓存配置
常用配置(默认时间单位都是秒)
• ResourceProperties.Cache
配置在ResourceProperties.Cache中设置的
• spring.resources.cache.cachecontrol.max-age=时间
最大缓存时间
• spring.resources.cache.cachecontrol.no-cache=true/false
关闭缓存
• spring.resources.cache.cachecontrol.s-max-age=时间
缓存资源的最长时间
Controller 中手工设置缓存
例子如下:
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id){
Book book=findBook(id);
String version=book.getVersion();
return ResponseEntity
.ok()
.cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
.eTag(version)
.body(book);
}
例子
目录如下:
需要修改的类为:CoffeeController
@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) {
// 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 ResponseEntity<Coffee> getById(@PathVariable Long id) { //返回由Coffee变为ResponseEntity<Coffee>
Coffee coffee = coffeeService.getCoffee(id);
return ResponseEntity.ok() //响应为ok
.cacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS))//缓存为10秒
.body(coffee);//结果为coffee类
}
@GetMapping(path = "/", params = "name")
@ResponseBody
public Coffee getByName(@RequestParam String name) {
return coffeeService.getCoffee(name);
}
}
结果
访问静态资源图片:
相关参数如下:
注释掉spring.resources.cache.cachecontrol.max-age=20s 开启spring.resources.cache.cachecontrol.no-cache=true之后 我们可以看到 它没有使用缓存
查询咖啡
缓存属性如下:
建议的资源访问方式
针对用户的静态资源放在cdn上,由cdn为用户提供访问;当cdn回源时,会有一组静态的服务器为cnd的回源提供所需的服务。也有cms的服务,后台去配置这些静态资源。静态资源本身还可以添加缓存。另一方面,应用的请求可以通过gateway进入后台,在gateway上面,去添加特定路径的cachecontrol相关的设置。另外,我们也可以先让gateway去访问缓存层,先做一道缓存,对特定的URL做一个缓存,然后根据缓存访问应用。