文章目录
一、@RequestMapping注解
这个注解可以用于类或者方法上,并通过属性value指定请求路径
@GetMapping @PostMapping @PutMapping @DeleteMapping @PatchMapping
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
// 配置请求映射名称
String name() default "";
// 通过路径映射
@AliasFor("path")
String[] value() default {};
// 通过路径映射会path配置项
@AliasFor("value")
String[] path() default {};
// 限定只响应 HTTP 请求类型,如 GET, POST HEAD OPTIONS PUT TRACE
// 默认的情况下 可以响应所有的请求类型
RequestMethod[] method() default {};
// 当存在对应的 HTTP 参数时才响应请求
String[] params() default {};
// 限定请求头存在对应的参数时才响应
String[] headers() default {};
// 限定 请求体提交类型 application/json, text/html ”
String[] consumes() default {};
// 限定返回的内容类型,仅当 HTTP 请求头中的( Accept )类型中包含该指定类型时才返回
String[] produces() default {};
}
示例:
// 带占位符的URL
@RequestMapping(value = "user/{userId}/order/{orderNumber}", method = RequestMethod.GET)
public ModelAndView OrderInfo4(@PathVariable int userId,@PathVariable String orderNumber) {
return new ModelAndView("order/info", "message", "userid:"+userId+" orderNumber:"+orderNumber);
}
// 带占位符的URL 支持正则表达式风格的URL路径映射
// ? 匹配一个字符
// * 匹配路径段中的零个或多个字符
// ** 匹配零个或多个路径段
// 可以匹配http://localhost:8080/orderXXXXX?orderNumber=yyyy
@RequestMapping(value = "order*", method = RequestMethod.GET)
//@RequestMapping(value = "order?", method = RequestMethod.GET)
//@RequestMapping(value = "order/**", method = RequestMethod.GET)
public ModelAndView OrderInfo5(String orderNumber) {
return new ModelAndView("order/info", "message", "OrderInfo5");
}
// params 限定参数值 // params = "orderNumber"
@RequestMapping(value = "detail3", params = "orderNumber!=1222" )
public ModelAndView Detail3(String orderNumber) {
return new ModelAndView("order/info", "message", orderNumber);
}
@RequestMapping(value = "headtest",headers = "apikey=23131313")
@RequestMapping(value = "headtest",headers= {"Accept=application/json"})
// 通过consumes指定请求提交的内容类型(Content-Type)
@RequestMapping(value = "consumes", method = RequestMethod.POST, consumes = "application/json")
// produces属性用于设定返回内容类型
@RequestMapping(value = "produces", method = RequestMethod.GET, produces = "application/json")
二 、 获取请求参数
1. 在无注解下获取参数
在没有注解的情况下 SpringMVC 也可以获取参数,且参数允许为空,唯一要求是参数名称HTTP请求的参数名称保持一致
// http://localhost:8080l/no/annotation?intVal=10&longVal=200
public String controller(Interger intVal, Long longVal,String str)
2. 使用@RequestParam 获取参数
// http://localhost:8080l/no/annotation?int_val=10&longVal=200
// @RequestParam(val="int_val", required=false) 默认不能为空,可为空设置false
public String controller(@RequestParam("int_val") Interger intVal, Long longVal,String str)
3. 传递数组
// http://localhost:8080l/no/annotation?intArr=10,11,12
public String controller(@RequestParam("int_val") int[] intArr)
4. 传递 JSON
// 请求 contentType : "application/json”,
// @RequestBody注解得到 JSON 参数
public User insert(@RequestBody User user)
5. 通过 URL 传递参数(REST)
// http://localhost:8080l/user/12
@GetMapping ("user/{id}")
public User get( @PathVariable("id") Long id)
6. 获取格式化参数(如日期,货币)
@ DateTimeFormat 、@NumberFormat
Spring Boot 中, 日期参数的格式化也可以不使用@DateTimeFormat ,而 只在配置文件application.properties 中加入如下配置项即可
spring . mvc . date-format=yyyy-MM-dd
public Map<String , Object> format(
@DateTimeFormat(iso=ISO.DATE) Date date ,
@NumberFormat(pattern =”#,###.##”) Double number) {
三、自定义参数转换规则
1. 一对一转换器(Converter)
也就是从一种类型转换为另外一种类型, public interface Converter<S, T>
// http://localhost:8080/my/converter?person=1-xiaohuahua-beautiful
@Component //
public class StringToPersonConverter implements Converter<String, Person> {
//转换方法
@Override // Spring就会将这个类扫描并且装配到IoC容器中
public Person convert(String person) {
// 把 person字符串 转成 Person对象
return person;
}
}
@GetMapping("/converter")
@ResponseBody
public Person getPersonByConverter(Person person){
return person;
}
二、GenericConverter集合和数组转换
因为SpringMVC自身提供了一些数组转换器,需要自定义的并不多,所以这里只介绍SpringMVC自定义的数组转换器
四、数据验证
1. JSR-303验证
public class ValidatorPojo {
//非空判断
@NotNull(message = "id不能为空")
private Long id;
//只能是将来日期
@Future(message = "需要一个将来日期")
//@Past //只能是过去的日期
@NotNull
private Date date;
@NotNull //不能为空
@DecimalMin(value = "0.1")//最小值0.1
@DecimalMax(value = "10000.00")//最大值10000.00
private Double doubleValue = null;
@NotNull //不能为空
@Min(value = 1,message = "最小值为1") //最小值为1
@Max(value = 88,message = "最大值为88") //最大值为88
private Integer integer;
@Range(min=1,max=888,message = "范围为1到888")//限定范围
private Long range;
@Email(message = "邮箱格式错误") //邮箱验证
private String email;
@Size(min=20,max=30,message = "字符串长度要求20到30之间")
private String size;
}
@RequestMapping(value ="/valid/validate")
@ResponseBody
public Map<String,Object> validate(
@Valid @RequestBody ValidatorPojo validatorPojo, Errors errors){
Map<String,Object> errMap=new HashMap<>();
//获取错误列表
List<ObjectError> oes=errors.getAllErrors();
for(ObjectError oe:oes){
String key=null;
String msg=null;
//字段错误
if(oe instanceof FieldError){
FieldError fe= (FieldError) oe;
key=fe.getField();//获取错误验证字段名
}else {
//非字段错误
key=oe.getObjectName();//获取验证对象名称
}
//错误信息
msg=oe.getDefaultMessage();
errMap.put(key,msg);
}
return errMap;
}
2. Validator接口
public class PersonValidator implements Validator {
//该验证器支持Person类的验证
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(Person.class);
}
//验证逻辑
@Override
public void validate(Object target, Errors errors) {
//对象为空
if(target==null){
//直接在参数处报错,这样就不能进入控制器的方法
errors.rejectValue("",null,"用户不能为空");
return;
}
//强制转换
Person person=(Person)target;
//用户名非空串
if(StringUtils.isEmpty(person.getPersonName())){
//增加错误,可以进入控制器方法
errors.rejectValue("personName","null","用户名不能为空");
}
}
}
/**
*
* @Description:调用控制器前执行这个方法
*/
@InitBinder
public void initBinder(WebDataBinder webDataBinder){
//绑定验证器
webDataBinder.setValidator(new PersonValidator());
//定义日期格式参数,参数不再需要注解@DateTimeFormat,boolean参数表示是否允许为空
webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),false));
}
@RequestMapping(value ="/valid/personValid")
@ResponseBody
public Map<String,Object> personValid(
@Valid Person person,
Errors errors,
Date date){}
五、数据模型
- ModelAndView构造方法可以指定返回的页面名称(return new ModelAndView(“redirect:/m07.jsp”);),
也可以通过setViewName()方法跳转到指定的页面 , - 使用addObject()设置需要返回的值,addObject()有几个不同参数的方法,可以默认和指定返回对象的名字
注意:如果在控制器方法的参数中使用 ModelAndView Model Mode!Map 作为参数
类型, SpringMVC 会自动创建数据模型对象
public String useModel(Long id, Model model){
model.addAttribute("user", User);
return "data/user"
}
public ModelAndView useModelMap(Long id, ModelMap modelMap){
ModelAndView mv = new ModelAndView();
mv.setViewName("data/user");
modelMap.put("user", User)
return mv;
}
public ModelAndView useModelAndView(Long id, ModelAndView mv){
mv.setViewName("data/user");
mv.addObject("user", User)
return mv;
}
/*
先创建ModelAndView对象,再通过它的方法去设置数据与转发的视图名:
setViewName(String viewName):设置此 ModelAndView 的视图名称, 由 DispatcherServlet 通过 ViewResolver 解析
addObject(String attributeName, Object attributeValue):通过key/value的方式绑定数据
*/
public ModelAndView m06() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("m06");
modelAndView.addObject("message", "Hello World, Hello Kitty");
return modelAndView;
}
// 可以直接通过带有参数的构造方法 ModelAndView(String viewName, String attributeName, Object attributeValue) 来返回数据与转发的视图名。
public ModelAndView m07() {
return new ModelAndView("m07", "message", "Hello World");
}
// 设置重定向
public ModelAndView m07(@PathVariable String name) {
if (!"admin".equals(name)) {
return new ModelAndView("redirect:/m07.jsp");
}
return new ModelAndView("m07");
}
六、拦截器
SpringMVC拦截器执行顺序原理解释
https://blog.csdn.net/shijiujiu33/article/details/88146502
责任链模式规则,(preHandle)先注册先执行,(postHandle,afterCompletion) 是先注册后执行.
preHandle方法一旦返回false,后续的拦截器、处理器和所有拦截器的postHandle都不会被执行。afterCompletion指挥执行返回true的拦截器的方法,顺序先注册后执行。
1.通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
public class LoginInterception implements HandlerInterceptor {
//处理器方法映射之前执行
//返回true,放行;false,不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("处理器方法映射之前执行");
return true;
}
//处理器方法映射执行之后会自动调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理器方法映射执行之后会自动调用");
}
//所有请求完成之后调用
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("所有请求完成之后调用");
}
}
// 在springmvc的配置文件里面进行配置
<mvc:interceptors>
<!--自定义拦截器(拦截所有请求)-->
<bean class="fei.springmvc.interceptor.FristInterception"></bean>
<!--自定义拦截器(拦截指定请求)-->
<mvc:interceptor>
<mvc:mapping path="/intercep"/> // 拦截指定请求
// <mvc:exclude-mapping path=""/> 配置拦截除此之外的所有请求
<bean class="fei.springmvc.interceptor.LoginInterception"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器配置类
/*
拦截器配置类
实现 WebMvcConfigurer, 覆盖 addInterceptors 进行注册拦截器
*/
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())//添加拦截器
.addPathPatterns("/**") //拦截所有请求
.excludePathPatterns("/UserCon/**", "/Doctor/**", "/SMS/**");//对应的不拦截的请求
}
}
七、文件上传
Spring Boot 文件上传与下载
https://www.jianshu.com/p/e25b3c542553
八、国际化
九、Spring MVC 拾遗
一、重定向
// 重定向
return "show/user/"
return " redirect : /user/show?id= " + user.getid();
mv.setViewName("redirect:/user/show?id= " + user.getid())
// 重定向传递 Java 对象
@RequestMapping("/method1")
public String method1(RedirectAttributes ra){
ra.addAttribute("user",user);
return "redirect:method2.do";
}
@RequestMapping("/method2")
public ModelAndView method2(String user){
ModelAndView mav = new ModelAndView();
mav.setViewName("index");
mav.addObject("user", user);
return mav;
}
二、操作会话对象
1. 通过原生session对象
// 通过原生session对象
@RequestMapping("/getSession")
public String getSession(User user,HttpSession session){
session.setAttribute("CURR_USER", user);
return "index";
}
}
2. @SessionAttributes
通过在控制类上方加入注解@SessionAttributes(value={“CURR_USER”},types={User.class})来指定session值的类型以及key值,通过方法中类型或者key值的匹配来实现自动往session中赋值
注意:在注解中key值或类型有任意一个匹配,此对象都会被赋值到session域中
如果不写注解@SessionAttributes(value={“CURR_USER”},types={User.class}),则其作用域为request