核心依赖包
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
请求处理
主要列举下几个核心注解
@Contrller
- 位置:类
- 作用:表示这个类是有一个控制器
- 说明:一般是需要搭配一个
@RequestMapping
注解,配置这个控制器的路径
- 注意:在没有
@ResponseBody
搭配的情况下,需要增加模板引擎依赖否则会报错
@ResponseBody
- 位置:类或方法
- 作用:告诉控制器,这个Action甚至整个Controller,返回的对象都将会序列化成JSON,并回传给HttpResponse
@RestController
- 位置:类
- 作用:快捷注解,相当于给类添加
@Contrller
+@ResponseBody
,2个注解
@RequestMapping
位置:类或方法
作用:几个参数及作用
value:指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method:指定请求的method类型, GET、POST、PUT、DELETE等;
consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
@GetMapping
- 位置:类或方法
- 作用:快捷注解,作用同
@RequestMapping
,只是限定了method=GET
@PostMapping
- 位置:类或方法
- 作用:快捷注解,作用同
@RequestMapping
,只是限定了method=POST
获取请求数据
获取常规请求参数
这里指的是Query String和Form中的参数
- Form参数只有在
POST
请求中才会获取
- 如果在
POST
请求中,Query String和Form,存在相同的参数,则最后会取Form的参数
例如:获取以下请求中的userName参数
1
| /user/update/123?userName=zhangshan
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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;
@RestController @RequestMapping(value = "/user") public class TestController {
@PostMapping(value = "/update/{userId}") public String update(@RequestParam String userName){ return userName; } }
|
获取url中的path变量
- 需要预先在
@RequestMapping
中定义
- 给参数加上@PathVariable
例如:获取以下请求url中的123
1
| /user/update/123?userName=zhangshan
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import org.springframework.web.bind.annotation.*;
@RestController @RequestMapping(value = "/user") public class TestController { @PostMapping(value = "/update/{userId}") public String update( @RequestParam String userName, @PathVariable String userId ){ return userId+"-"+userName; } }
|
将请求参数绑定到java对象上
TestBean.java
1 2 3 4 5 6 7
| import lombok.Data;
@Data public class TestBean { private Integer userId; private String userName; }
|
TestController.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| import org.springframework.web.bind.annotation.*;
@RestController @RequestMapping(value = "/user") public class TestController {
@PostMapping(value = "/update/{userId}") public String update( TestBean testBean ){ return testBean.getUserId()+"-"+testBean.getUserName(); } }
|
经过测试,直接将请求参数绑定到java对象。优先级如下:
- url的query参数
- form的参数
- url的path参数
如果多处存在相同名称参数,优先级高的会覆盖优先级低的
获取json请求,并绑定到java对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.example.demo;
import org.springframework.web.bind.annotation.*;
@RestController @RequestMapping(value = "/user") public class TestController {
@PostMapping(value = "/update/{userId}") public String update( @RequestBody TestBean testBean ){ return testBean.getUserId()+"-"+testBean.getUserName(); } }
|
@RequestBody
- 该注解,可以将客户端,发起post请求时,将request body中的json,直接映射成java对象
- json可以拿过来提交嵌套结构的对象,降低参数接收的复杂度
数据校验
@Valid 和 @Validated
@Valid
- 所在包:javax.validation.Valid
- 属于JSR-303规范
@Validated
- 所在包:org.springframework.validation.annotation.Validated
- @Validated是@Valid的一次封装,不是规范。
@Validated
相对于@Valid
,增加了分组校验
- 在spirng开发中,我想应该更加推荐使用
基本验证规则
注解 |
可校验类型 |
说明 |
@AssertFalse |
Boolean,boolean |
验证注解的元素值是false |
@AssertTrue |
Boolean,boolean |
验证注解的元素值是true |
@NotNull |
任意类型 |
验证注解的元素值不是null |
@Null |
任意类型 |
验证注解的元素值是null |
@Min(value=值) |
BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型 |
验证注解的元素值大于等于@Min指定的value值 |
@Max(value=值) |
和@Min要求一样 |
验证注解的元素值小于等于@Max指定的value值 |
@DecimalMin(value=值) |
和@Min要求一样 |
验证注解的元素值大于等于@ DecimalMin指定的value值 |
@DecimalMax(value=值) |
和@Min要求一样 |
验证注解的元素值小于等于@ DecimalMax指定的value值 |
@Digits(integer=整数位数, fraction=小数位数) |
和@Min要求一样 |
验证注解的元素值的整数位数和小数位数上限 |
@Size(min=下限, max=上限) |
字符串、Collection、Map、数组等 |
验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小 |
@Past |
java.util.Date,java.util.Calendar;Joda Time类库的日期类型 |
验证注解的元素值(日期类型)比当前时间早 |
@Future |
与@Past要求一样 |
验证注解的元素值(日期类型)比当前时间晚 |
@NotBlank |
CharSequence子类型 |
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格 |
@Length(min=下限, max=上限) |
CharSequence子类型 |
验证注解的元素值长度在min和max区间内 |
@NotEmpty |
CharSequence子类型、Collection、Map、数组 |
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@Range(min=最小值, max=最大值) |
BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型 |
验证注解的元素值在最小值和最大值之间 |
@Email(regexp=正则表达式,flag=标志的模式) |
CharSequence子类型(如String) |
验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式 |
@Pattern(regexp=正则表达式,flag=标志的模式) |
String,任何CharSequence的子类型 |
验证注解的元素值与指定的正则表达式匹配 |
@Valid |
任何非原子类型 |
指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证 |
校验示例
Book.java
1 2 3 4 5 6 7 8 9 10 11 12
| import lombok.Data; import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data public class Book { @NotNull(message = "课本ID,不能为空") private Integer bookId; @NotBlank(message = "课本名称,不能为空") private String bookName; }
|
Stu.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import lombok.Data; import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.List;
@Data public class Stu {
@NotNull(message = "学号,不能为空") private Integer stuId;
@NotNull(message = "姓名,不能为空") private String stuName;
@NotEmpty(message = "课本列表,不能为空") @Valid private List<Book> bookList; }
|
TestController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping(value = "/user") public class TestController {
@PostMapping(value = "/test") public String test(@RequestBody @Validated Stu stu, BindingResult bindingResult) throws JsonProcessingException { if (bindingResult.hasErrors()) { return bindingResult.getFieldError().getDefaultMessage(); } ObjectMapper mapper = new ObjectMapper(); return "提交成功" + mapper.writeValueAsString(stu); } }
|
302重定向
1 2 3 4
| @GetMapping(value = "redirect") public void redirect(HttpServletResponse response) throws IOException { response.sendRedirect("http://www.baidu.com"); }
|
控制器之间跳转
1 2 3 4
| @GetMapping(value = "redirect2") public String redirect2() { return "redirect:/otherController/otherAction?param1=1¶m2=1"; }
|
自定义错误路由
ErrorConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.web.servlet.ErrorPage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus;
@Configuration public class ErrorConfig { @Bean public EmbeddedServletContainerCustomizer containerCustomizer(){ return container -> { container.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST,"/400")); container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/500")); container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,"/404")); container.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED,"/401")); }; } }
|
ErrorCtrl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;
@RestController public class ErrorCtrl { @RequestMapping(value = "/500") public String serverError(){ return "500"; } @RequestMapping(value = "/400") public String badRequest(){ return "400"; } @RequestMapping(value = "/404") public String notFound(){ return "404"; } }
|
添加拦截器
第一步:首先需要添加一个拦截器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@Component public class UrlPrintInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println(request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
} }
|
3个需要实现的方法,就不细说了,百度一大堆。请自行了解。
这里是一个很简单的拦截器,当请求进来的时候,把请求的uri打印出来。
第二部:添加一个WebMvc的配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import cn.cnvp.fw.saas.mch.web.interceptor.UrlInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration public class MvcConfig implements WebMvcConfigurer { @Bean public HandlerInterceptor getUrlInterceptor(){ return new UrlInterceptor(); } public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(getUrlInterceptor()) .addPathPatterns("/**"); } }
|
添加注册,并指定拦截的路径。大功告成。
jar包外静态资源的访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import cn.cnvp.hx.saas.tmp1.Application; import org.springframework.boot.system.ApplicationHome; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.IOException;
@Configuration public class MvcConfig implements WebMvcConfigurer { @Bean public static String getJarDir() { ApplicationHome home = new ApplicationHome(Application.class); System.out.println(home.getDir()); try { return home.getDir().getCanonicalPath(); } catch (IOException e) { return null; } } public void addResourceHandlers(ResourceHandlerRegistry registry) { System.out.println(getJarDir()); registry.addResourceHandler("/**").addResourceLocations("file:"+getJarDir()+"/"); registry.addResourceHandler("/uploads/**").addResourceLocations("file:"+getJarDir()+"/upload"); }
}
|