SpringMVC学习笔记

准备工作

1.配置web.xml

 

 

(也可以设置不全拦截,加上这两句:
<mvc:default-servlet-handler/>
<mvc:annotation-driven></mvc:annotation-driven>
加上之后SpringMVC会对请求进行筛查,如果确实有对该映射的处理,就正常跳转,如果没有则由默认的 Servlet处理)
2.配置mvc的配置文件
2.1 配置自动扫描的包
2.2 配置视图解析器
(InternalResourceViewResolver是将方法返回的值和prefix和suffix拼接成实际的物理视图)
(BeanNameViewResolver:若方案的返回值是一个bean名(就是类名首字母小写),就会直接返回这个类的实例)
 
一. @RequestMapping
Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求
@RequestMapping可以在两个位置进行标注
  1. 类定义的上面:提供初步请求映射,相当与从根目录开始
  2. 方法的上面:进一步细分映射,若类定义处标注了@RequestMapping,则方法出标注的映射就是接着类之后的映射,若类没有标注,则相当与从根目录开始

(相当于处理URL为"/wbw/lzy"的请求)
 
@RequestMapping还可以加上请求方法条件
(他们之间是与关系,必须都满足才能对将请求映射到这个类或者这个方法上)
 
二. 通过URL得到参数的几种方式
  • 基本数据类型传递
SpringMVC会自动帮我们给参数注入值,这里只需要我们的参数名称和index.jsp里面input的name相同即可

 

  • @PathVariable
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中 ,
详细来说:URL 中的 {xxx} 占位符可以通过@PathVariable("xxx") 绑定到操作方法的入参中。
 
例:url为"delete/123"
(则id=123)

 

 

  • @RequestParam
在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
 
例:url为"handle5?username=wbw&age=20"
(则在方案中可以直接调用usernam和age,值为wbw和20)
 
三. Servlet原生的API可以作为Handle方法的参数,支持的类型包括
  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
  • java.security.Principal
  • Locale
  • InputStream
  • OutputStream
  • Reader
  • Writer
例:
(可以在控制台输出:hello springmvc)
 
四. POJO
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性(意思就是会根据请求参数自动给对象填充属性,但是必须保证请求参数名和属性名是一致的)
 
例:
一个表单:
其jsp是:
提交之后映射到这个方法上,springmvc会自动为user对象添加各个属性

 

 

 
五. 处理模型数据
有ModleAndView和Map种选择
  • ModelAndView
当控制器处理完请求时,通常会将包含视图名称或视图对象以及一些模型属性ModelAndView对象返回到DispatcherServlet。(将数据输出到页面上换句话说就是把这个模型放到请求域里了)
作用:
1.返回到指定的页面
ModelAndView构造方法可以指定返回的页面名称
     例:return new ModelAndView("redirect:/m07.jsp")
            return new ModelAndView("hello");
通过setViewName()方法跳转到指定的页面
     例:mav.setViewName("hello");
2.返回参数到指定页面的request作用于中
使用addObject()设置需要返回的值,addObject()有几个不同参数的方法,可以默认和指定返回对象的名字,参数会返回到新页面的request作用域中
@Controller
public class Test_ModelAndView {
 
 
    @RequestMapping("Test_ModelAndView")
    public ModelAndView test(){
        ModelAndView mv=new ModelAndView();
        //ModelAndView mv=new ModelAndView("welcome");//返回的文件名,和下一行一样的效果
         mv.setViewName("welcome"); //返回的文件名  
 
 
            mv.addObject("message","hello kitty");  
 
 
            //类
            User user = new User();
            user.setAge(20);
            user.setName("nihao");
            mv.addObject("user",user);  
 
 
            //List  
            List<String> list = new ArrayList<String>();  
            list.add("java");  
            list.add("c++");  
            list.add("oracle");  
            mv.addObject("bookList", list);  
 
 
            //Map  
            Map<String,String> map = new HashMap<String,String>();  
            map.put("zhangsan", "北京");  
            map.put("lisi", "上海");  
            map.put("wangwu", "深圳");  
            mv.addObject("map",map);  
 
 
            return mv;  
 
 
    }
}
然后在jsp页面可以输出数据
welcom.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Insert title here</title></head><body><body>  
   <!-- 输出普通字符 -->  
   ${message } <br/>  
   <!-- 输出List -->  
   <p>书籍列表</p>  
   <c:forEach items="${bookList}" var="node">  
        <c:out value="${node}"></c:out>  
   </c:forEach>  
   <br/>  
   <br/>  
 
 
   ${user }<br/>  
   <br/>
  <table border="1">
  <tr>
    <th>Month</th>
    <th>Savings</th>
  </tr>
  <tr>
    <td>${user.name }</td>
    <td>${user.age }</td>
  </tr></table>
     <br/>  
   <br/>
   <!-- 输出Map -->  
   <c:forEach items="${map}" var="node">  
        姓名:<c:out value="${node.key}"></c:out>  
        住址:<c:out value="${node.value}"></c:out>  
        <br/>  
   </c:forEach>  
</body>  
</body></html>
输出的结果:

 

 

 
  • Map(Model,ModelMap)
——Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
——如果方法的入参 Map Model ,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据
 
例:

 

 

(那么在jsp中写${requestScope.names}就可以在页面上显示[Tom,Jerry,Mike])
 
ModelAndView和Map区别?
答: ModelAndView的实例是需要我们手动new的,并且ModelAndView 可以自己寻址(因为setViemName方法设置了他指向的文件名),只需要return 返回其对象即可。而Map 的实例都是spirng mvc框架来自动创建并作为控制器方法参数传入,不用自己创建需要return 返回指定的页面路径.
 
六. REST
浏览器 form 表单只支持 GET与 POST 请求,而DELETE、PUT 等 method 并不支持,Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与DELETE 请求。
 
配置过程:
1.在web.xml文件中配置HiddenHttpMethodFilter,可将post请求转为put和delete
       <filter>
             <filter-name>HiddenHttpMethodFilter</filter-name>
             <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
       </filter>
       <filter-mapping>
             <filter-name>HiddenHttpMethodFilter</filter-name>
             <url-pattern>/*</url-pattern>
       </filter-mapping>
然后在

 

 

(发送post请求时携带一个name=_method的隐藏域,hiddenfilter会识别这个名字,并把其隐藏域对应的value值转为对应的请求方法发出去,这里发的就是put类型的请求)
 
七. ModelAttribute
@ModelAttribute最主要的作用是将数据添加到模型对象中(可用来完成从表单将数据传递给model对象的功能)
 
注:在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
 
运行流程:
1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user
@ModelAttribute
    public void getUser(@RequestParam(value="id",required=false) Integer id,
            Map<String, Object> map){
        System.out.println("modelAttribute method");
        if(id != null){
            //模拟从数据库中获取对象
            User user = new User(1, "Tom", "123456");
            System.out.println("从数据库中获取一个对象: " + user);
            
            map.put("user", user);
        }
    }
(原始数据:1 Tom 123456)
2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
(表单中输入了密码,输入值为56789)[方法是入参:在进行数据绑定之前,先到请求范围当中查找指key(POJO类的首字母小写)对应的value值对象,就是下面对应的user]
3. SpringMVC 把上述对象传入目标方法的参数.
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println("修改: " + user);
        return SUCCESS;
    }
(输出数据:1 Tom 56789
 
例2:
———————————————————————————————
* 源代码分析的流程
     * 1. 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.
     * 2. 解析请求处理器的目标参数, 实际上该目标参数来自于 WebDataBinder 对象的 target 属性
     * 1). 创建 WebDataBinder 对象:
     * ①. 确定 objectName 属性: 若传入的 attrName 属性值为 "", 则 objectName 为类名第一个字母小写.
     * *注意: attrName. 若目标方法的 POJO 属性使用了 @ModelAttribute 来修饰, 则 attrName 值即为 @ModelAttribute
     * 的 value 属性值
     *
     * ②. 确定 target 属性:
     *     > 在 implicitModel 中查找 attrName 对应的属性值. 若存在, ok
     *     > *若不存在: 则验证当前 Handler 是否使用了 @SessionAttributes 进行修饰, 若使用了, 则尝试从 Session 中
     * 获取 attrName 所对应的属性值. 若 session 中没有对应的属性值, 则抛出了异常.
     *     > 若 Handler 没有使用 @SessionAttributes 进行修饰, 或 @SessionAttributes 中没有使用 value 值指定的 key
     * 和 attrName 相匹配, 则通过反射创建了 POJO 对象
     *(简单来说attrName属性为名字,target属性为对应的值或者对象)
 
     * 2). SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性.
     *(会用表单传来的值对原来的target属性对应的值进行更新)
 
     * 3). *SpringMVC 会把 WebDataBinder 的 attrName 和 target 给到 implicitModel.
     * 近而传到 request 域对象中.
     * 4). 把 WebDataBinder 的 target 作为参数传递给目标方法的入参.
———————————————————————————————
 
八. 重定向和转发
  • 一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
  • 如果返回的字符串中带 forward: 或者 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理
 
例:
– redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
– forward:success.jsp:会完成一个到 success.jsp 的转发操作
 
九. mvc:view-controller

 

 
 
 
九. <mvc:annotation-driven/>
配置mvc:annotation-driven就是开启了注解驱动,Spring知道了我们开启了注解驱动后就可以通过context:component-scan/标签的配置,会自动为我们将扫描到的@Component,@Controller,@Service,@Repository等注解标记的组件注册到工厂中,来处理我们的请求。
 
他其中的一些标签:
 
  • <mvc:default-servlet-handler />
如果不设置这个标签,所有URL请求都将被Spring MVC的DispatcherServlet截获。设置了这个标签之后他会对URL进行筛查:
静态资源的请求转由Web应用服务器默认的Servlet处理
不是静态资源的请求→才由DispatcherServlet继续处理。
 
  • <mvc:view-controller />
还是上面的问题,如果希望发送的请求不通过controller,直接跳转到目标页面,可以设置这个标签
例:
<mvc:view-controller path="/hello" view-name="123"></mvc:view-controller>
—path=”/hello” 就是你访问的路径(相当于RequestMapping(“/hello”))
—view-name=”hello”是你所要的视图(如123.jsp,相当于return “123”) 配置了这个后对于/hello请求,就会直接交给dispatcherServlet,然后使用ViewResolver进行解析。
相当有代码:
@RequestMapping(value="/hello") 
public String hello(){ 
    System.out.println("hello"); 
    return "hello"; 
}
还可以配置重定向和转发
<mvc:view-controller path="/index" view-name="redirect:hello"></mvc:view-controller>
相当于
@RequestMapping("/index")
public String index(){
    return "redirect:hello";
}
 
  • 数据格式化(配置<mvc:annotation-driven/>就可以
1.日期格式化 @DateTimeFormat
@DateTimeFormat(pattern = "yyyy-MM-dd")   //这就是格式化,当输入字符串为(yyyy-MM-dd)类型的时候就会自动转化为Date类型:
private Date birthday;
pattern属性(必须):类型为字符串,指定解析/格式化字段数据的模式
2.数字类型格式化 @NumberFormat
@NumberFormat(pattern = "#,###,###.##")    //这个就是一个通用式了,无论多少数字都可以转为double类型
private double money;
pattern属性(必须):类型为字符串
 
  • @Vaild——数据校验
只要在 Spring 容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。
<mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean
所以想实现校验需要:
1.在处理方法的入参上标注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作
2.在bean的需要检验的属性上标注注解
 
——————————————————————————————————
注解包括:

 

 

——————————————————————————————————
 
例:
public class User implements Serializable {
 
 
    @NotNull(message = "uid不能为空")
    @Min(value = 1, message = "pid必须为正整数")
    private Long uid;
 
 
    @NotBlank(message = "userName不能为空")
    private String userName;
 
 
    @NotBlank(message = "address 不能为空")
    private String address;
    // getter/setter
}
 
@RequestMapping("/user/saveUser")
public String saveUser(@Valid User user, BindingResult bindingResult) {
    
    if (bindingResult.hasErrors()) {
        // 打印全部的错误信息
        for (ObjectError error : bindingResult.getAllErrors()) {
            System.out.println(error.getDefaultMessage());
        }
    }
    
    // 返回第一条的错误信息
    if (bindingResult.hasErrors()) {
         String msg=bindingResult.getAllErrors().get(0).getDefaultMessage();
         return msg;
     }
}
 
 

 

 

并且,校验的结果会被保存在被校验入参对象(上文对应的是user)之后的 BindingResult 或Errors 入参中(需校验的 Bean 对象和其绑定结果对象或错误对象时成对出现的,它们之间不允许声明其他的入参
Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或getFieldErrors(String field)
—BindingResult 扩展了 Errors 接口
其常用方法:
-getAllErrors(返回的是error数组)
-getDefaultMessage()(返回的是设置的错误提示信息)
 
错误信息不仅可以存在Error或BindingResult对象中,还会保存到“隐含模型”,隐含模型会暴露给JSP,所以在JSP中可以获取错误信息
通过: <form:errors path=“xxx”>显示错误消息
例:

 

 

 

 

 

posted @ 2020-02-22 19:54  BeeeenWei  阅读(223)  评论(0)    收藏  举报