SpringMVC-基础知识


注解 说明
@RequestMapping 告诉SpringMVC,这个方法用来处理什么请求
@PathVariable 接收请求路径中占位符的值
@RequestParam 获取请求参数;默认请求参数必须有否则报错
@RequestHeader 获取请求头中某个key的值;如果请求头中没有指定的参数,则会报错
@CookieValue 获取某个Cookie值;默认如果没有的话会报错
@SessionAttributes 往Session中输出数据,但不推荐使用
@ModelAttribute SpringMVC在调用目标处理方法前会先逐个调用在方法级上标注了@ModelAttribute的方法
@DateTimeFormat 日期格式化
@NumberFormat 数值格式化
@Null 被注释的元素必须为null(JSR303标注在Bean属性上)
@NotNull 被注释的元素必须不为null
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min) 被注释的元素必须的大小必须在指定的范围内
@Digits(integer,fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Futrue 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
@Email 被注释的元素必须是电子邮箱地址(Hibernate Validator)
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串必须非空
@Range 被注释的元素必须在合适的范围内
@valid 在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验
@ResponseBody 响应体数据直接输出到浏览器页面
@RequestBody 获取请求体消息内容
@RestController
@ControllerAdvice 标注在类上,标明此类专门用来处理异常
@ExceptionHandler 处理异常
@ResponseStatus 处理自定义异常







helloworld代码案例

  1. 加入JAR包
  2. 在web.xml中配置DispatcherServlet
  3. 加入SpringMVC配置文件
  4. 编写处理请求的处理器,并标识为处理器
  5. 编写视图
配置web.xml和springmvc.xml

    
    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
            
            contextConfigLocation
            classpath:springmvc.xml
        
        
        1
    
    
        springmvc
        /
    






    
    

准备页面

hello


success

处理请求的代码
@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login() {
        return "success";
    }
}

注解详解

@RequestMapping

SpringMVC使用 @RequestMapping 注解为控制器指定可以处理哪些URL请求(DispatcherServlet截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所对应的处理方法)

  • 类定义处:提供初步的请求映射信息。相对于WEB应用的根目录
  • 方法处:提供进一步的细分映射信息。相对于类定义处的URL。若类定义处未标注@RequestMapping,则方法处标记的URL相对于WEB应用的根目录

@RequestMapping 除了可以使用请求 URL 映射请求外,还可以使用请求方法、请求参数及请求头映射请求。@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射更加精确化。

  • params 和 headers支持简单的表达式:
    • param1: 表示请求必须包含名为 param1 的请求参数
    • !param1: 表示请求不能包含名为 param1 的请求参数
    • param1 != value1: 表示请求包含名为 param1 的请求参数,但其值不能为 value1
    • {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1

@RequestMapping支持Ant风格的URL格式(模糊匹配)

  • Ant风格资源地址支持3种匹配符(URL地址可以写模糊的通配符)
    • ? :匹配文件名中的一个字符
    • * :匹配文件名中的任意多个字符和一层路径
    • ** :匹配多层路径
  • @RequestMapping还支持Ant风格的URL
    • /user/ * /createUser : 匹配/user/aaa/createUser、/user/bbb/createUser等URL
    • /user/ ** /createUser : 匹配/user/createUser、/user/aaa/bbb/createUser等URL
    • /user/createUser?? : 匹配/user/createUseraa、/user/createUserbb等URL
@RequestMapping(value = "/login", method = RequestMethod.GET, params = {"username"}, headers = {"content-type=text/*"})
public String login() {
    return "success";
}
@RequestMapping属性 注解属性类型 说明
path String[] 请求路径
value String[] 请求路径
method RequestMethod[] 限定请求方式;默认是什么方式都可以
params String[] 规定请求参数
headers String[] 规定请求头
consumes String[] 只接受内容类型是哪种的请求,规定请求头中的Content-Type
produces String[] 告诉浏览器返回的内容类型是什么,给响应头中加上Content-Type:text/html;charset=utf-8

@PathVariable

@PathVariable映射URL绑定的占位符

  • 带占位符的URL是Spring3.0新增的功能,该功能在SpringMVC向REST目标挺进发展过程中具有里程碑的意义
  • 通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{xxx}占位符可以通过@PathVariable("xxx")绑定到操作方法的入参中
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id) {
    userDao.delete(id);
    return "redirect:/user/list.action";
}

Rest风格

在HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

// 普通方式
getOrder?id=1		GET
deleteOrder?id=1	GET
updateOrder			POST
saveOrder			POST


// Rest风格
/order/1  HTTP GET		得到id = 1的order
/order/1  HTTP DELETE	删除id = 1的order
/order/1  HTTP PUT		更新id = 1的order
/order    HTTP POST		新增order

浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,Spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。

  1. SpringMVC中有一个Filter,它可以把普通的请求转化为规定形式的请求
  2. 创建一个POST类型的表单,表单项中携带一个_method的参数,这个_method的值就是DELETE、PUT

注意:高版本Tomcat支持REST有点问题,可能会报405,所以要在success页面page指令中添加 isErrorPage=true 即可

配置REST风格的请求


    HiddenHttpMethodFilter
    org.springframework.web.filter.HiddenHttpMethodFilter


    HiddenHttpMethodFilter
    /*

@RequestMapping(value = "/book/{bid}", method = RequestMethod.DELETE)
public String deleteBook(@PathVariable("bid") Integer id) {
    System.out.println("删除图书");
    return "success";
}

@RequestMapping(value = "/book/{bid}", method = RequestMethod.PUT)
public String updateBook(@PathVariable("bid") Integer id) {
    System.out.println("更新图书");
    return "success";
}

@RequestParam

默认方式获取请求参数:直接给方法入参上写一个和请求参数名相同的变量,这个变量就来接收请求参数的值;如果请求URL中携带了指定的请求参数,就获取该值,如果没带该值,则返回null
如果请求参数和方法入参名不一致可以使用@RequestParam注解

在处理方法入参处使用@RequestParam可以把请求参数传递给请求方法

  • value:参数名
  • required:是否必须。默认为true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
  • defaultValue:默认值,没带参数的话可以指定默认值
// URL=/login?user=123
@RequestMapping(value = "/login")
public String login(@RequestParam(value = "user", required = false) String username) {
    return "success";
}

@RequestHeader

使用 @RequestHeader 绑定请求报头的属性值
请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中

  • value:参数名
  • required:是否必须。默认为true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
  • defaultValue:默认值,没带参数的话可以指定默认值
@RequestMapping(value = "/login")
public String login(@RequestHeader("Accept-Encoding") String encoding) {
    return "success";
}

@CookieValue

@CookieValue 可让处理方法入参绑定某个 Cookie 值

@RequestMapping(value = "/login")
public String login(@CookieValue(value="sessionId",required=false) String sessionId) {
    return "success";
}
@RequestMapping(value = "param")
public String param(@RequestParam(value = "user", required = false, defaultValue = "root") String username,
                    @RequestHeader(value = "User-Agent", required = false, defaultValue = "nothing") String userAgent,
                    @CookieValue(value = "JSESSIONID", required = false, defaultValue = "sessionid") String sessionId) {
    System.out.println("user: " + username);
    System.out.println("user-agent: " + userAgent);
    System.out.println("JSESSIONID: " + sessionId);
    return "success";
}

其他的请求处理操作

Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性

传入POJO自动封装
书名:
作者:
价格:
库存:
销量:
省: 市: 街道:
@Data
public class Book {
    private String bookName;
    private String author;
    private String price;
    private String stock;
    private String sales;
    private Address address;
}

@Data
public class Address {
    private String province;
    private String city;
    private String street;
}
@RequestMapping("/book")
public String addBook(Book book) {
    System.out.println("保存的图书" + book);
    return "success";
}
传入原生Servlet API
@RequestMapping(value = "/servlet")
public String javaee(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    request.setAttribute("requestParam", "request数据");
    return "success";
}

请求成功:${requestScope.requestParam}
CharacterEncoding解决乱码问题


    CharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
    
        encoding
        UTF-8
    
    
    
        forceEncoding
        true
    


    CharacterEncodingFilter
    /*

数据传出

Spring MVC 提供了以下几种途径输出模型数据:

  • Map、Model、ModelMap: 入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.uti.Map时,处理方法返回时,Map中的数据会自动添加到模型中
  • ModelAndView: 处理方法返回值类型为ModelAndView时, 方法体即可通过该对象添加模型数据
    • 控制器处理方法的返回值如果为ModelAndView, 则其既包含视图信息,也包含模型数据信息
  • @SessionAttributes: 将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性
  • @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
处理模型数据

通过Map输出数据
通过Model输出数据
通过ModelMap输出数据
通过ModelAndView输出数据

通过@ModelAttribute输出数据

书名:西游记
作者:
价格:
库存:
请求成功:${requestScope.msg}
@RequestMapping(value = "/handleMap")
public String handleMap(Map<String, Object> map) {
    map.put("msg", "Map数据");
    return "success";
}

@RequestMapping(value = "/handleModel")
public String handleModel(Model model) {
    model.addAttribute("msg", "Model数据");
    return "success";
}

@RequestMapping(value = "/handleModelMap")
public String handleModelMap(ModelMap modelMap) {
    modelMap.addAttribute("msg", "ModelMap数据");
    return "success";
}

@RequestMapping(value = "/handleModelAndView")
public ModelAndView handleModelAndView() {
    ModelAndView mv = new ModelAndView("success");
    mv.addObject("msg", "ModelAndView数据");
    return mv;
}


@SessionAttributes(value = {"msg","desc"},types ={String.class})
@Controller
public class LoginController {}


@RequestMapping(value = "/updateBook")
public String updateBook(@ModelAttribute("book") Book book) {
    System.out.println("页面提交过来的要修改信息" + book);
    return "success";
}

@ModelAttribute
public void beforeUpdateBook(Model model) {
    Book book = new Book("西游记", "吴承恩", 99, 99);
    System.out.println("数据库查询到的信息" + book);
    model.addAttribute("book", book);
}

视图解析

视图解析

SpringMVC的视图:SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户。SpringMVC视图的种类很多,默认有转发视图和重定向视图。当工程引入jstl的依赖,转发视图会自动转换为JstlView。若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView

  • ThymeleafView:当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转
  • 转发视图:SpringMVC中默认的转发视图是InternalResourceView。当控制器方法中所设置的视图名称以"forward:"为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转
    • 例如"forward:/",“forward:/employee”
  • 重定向视图:SpringMVC中默认的重定向视图是RedirectView。当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转
    • 例如"redirect:/",“redirect:/employee”
    • 重定向:就是从当前项目下开始的,SpringMVC会为路径自动拼接上项目名
  • 视图控制器view-controller:当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示
视图解析代码案例
请求转发方式一:上级目录
请求转发方式二:一级转发
请求转发方式三:多级转发

请求重定向方式一:一级重定向
请求重定向方式二:多级重定向
// 请求转发
@RequestMapping("/handle01")
public String handle01() {
    System.out.println("handle01");
    return "../../hello";
}

@RequestMapping("/handle02")
public String handle02() {
    System.out.println("handle02");
    return "forward:/hello.jsp";
}

@RequestMapping("/handle03")
public String handle03() {
    System.out.println("handle03");
    return "forward:/handle02";
}

// 请求重定向
@RequestMapping("/handle04")
public String handle04() {
    System.out.println("handle04");
    return "redirect:/hello.jsp";
}

@RequestMapping("/handle05")
public String handle05() {
    System.out.println("handle05");
    return "redirect:/handle04";
}

处理静态资源

优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀。若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获 WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理,因找不到对应处理器将导致错误。

  • 可以在 SpringMVC 的配置文件中配置 mvc:default-servlet-handler/ 的方式解决静态资源的问题
    • mvc:default-servlet-handler/ 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理
    • 一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定

注意:单一一个 mvc:default-servlet-handler/ 标签只能解决静态资源访问,动态映射的请求不行;所以需要同时添加 mvc:annotation-driven/ 标签。只有这两个标签都添加了才能保证动态请求和静态请求都能访问

处理静态资源方法




会自动注册RequestMappingHandlerMapping 、RequestMappingHandlerAdapter 与 ExceptionHandlerExceptionResolver 三个bean

  • 支持使用 ConversionService 实例对表单参数进行类型转换
  • 支持使用 @NumberFormat annotation、@DateTimeFormat 注解完成数据类型的格式化
  • 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
  • 支持使用 @RequestBody 和 @ResponseBody 注解

数据绑定流程

  • Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
  • DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
  • 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象
  • Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参

自定义类型转换器

  • ConversionService 是 Spring 类型转换体系的核心接口
  • 可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC 容器中定义一个 ConversionService. Spring 将自动识别出 IOC 容器中的 ConversionService,并在 Bean 属性配置及 Spring MVC 处理方法入参绑定等场合使用它进行数据的转换
  • 可通过 ConversionServiceFactoryBean 的 converters 属性注册自定义的类型转换器

数据格式化

对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴

  • Spring 在格式化模块中定义了一个实现 ConversionService 接口的 FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能

  • FormattingConversionService 拥有一个 FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者

  • FormattingConversionServiceFactroyBean 内部已经注册了

    • NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解(@NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性)
      • style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、 Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
      • pattern:类型为 String,自定义样式,如patter="#,###";
    • JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解(@DateTimeFormat可对 java.util.Date、java.util.Calendar、java.long.Long 时间类型进行标注)
      • pattern 属性:类型为字符串。指定解析/格式化字段数据的模式,如:”yyyy-MM-dd hh:mm:ss”
      • iso 属性:类型为 DateTimeFormat.ISO。指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用) -- 默认、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)、  ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
          - style 属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式:S:短日期/时间格式、M:中日期/时间格式、L:长日期/时间格式、F:完整日期/时间格式、-:忽略日期或时间格式
  • 装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。mvc:annotation-driven/ 默认创建的 ConversionService 实例即为 FormattingConversionServiceFactroyBean

其他

SpringMVC处理JSON

  1. 导入Jackson的依赖
  2. 在SpringMVC配置文件中开启MVC的注解驱动:此时在HandlerAdaptor中会自动装配一个消息转换器MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为JSON格式的字符串
  3. 在处理器方法上使用@ResponseBody注解进行标识
  4. 将Java对象直接作为控制器方法的返回值返回,就会自动转换为JSON格式的字符串