Sping mvc 杂文

一、@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){}


五、数据模型

  1. ModelAndView构造方法可以指定返回的页面名称(return new ModelAndView(“redirect:/m07.jsp”);),
    也可以通过setViewName()方法跳转到指定的页面 ,
  2. 使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值