SpringMVC学习笔记2(注解)

作者: 页川叶川 | 来源:发表于2019-04-23 22:07 被阅读2次

    第二部分 注解

    1.@Controller:

    @Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。
    但是单单使用@Controller 标记在一个类上还不能真正意义上的说它就SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。

    这个时候有两种方式可以把MyController 交给Spring 管理,好让它能够识别我们标记的@Controller 。
    第一种方式是在SpringMVC 的配置文件中定义MyController 的bean 对象。

    <bean class="com.host.app.web.controller.MyController"/>
    

    第二种方式是在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。

    < context:component-scan base-package = "com.host.app.web.controller" >
           < context:exclude-filter type = "annotation" expression = "org.springframework.stereotype.Service" />
    </ context:component-scan > 
    

    2.@RequestMapping

    • SpringMVC使用@RequestMapping注解为控制器指定可以处理哪些URL请求
      在控制器的类定义与方法定义处都可标注
    • @RequestMapping
      -类定义处:提供初步的请求映射信息。相对于WEB应用根目录
      -方法处:提供进一步的细分映射信息。相对于类定义的URL。若类定义处未标注@RequestMapping,则方法处标记的URL相对于WEB根目录
    • DispatherServlet截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所对应的处理方法
    映射请求参数、请求方法或请求头
    映射请求参数、请求方法或请求头.png
    • method 可以用来定义请求的方式
    • params 和 headers 可以用来发送更加精确的映射请求。params 和 headers 支持简单的表达式
    @RequestMapping(value="/testMethod",method = RequestMethod.POST)
        public String testMethod() {
            System.out.println("testMethod");
            return SUCCESS;
        }
    
        /*
        * 了解:可以使用 params 和 headers 来更加精确的映射请求。params 和 headers 支持简单的表达式
        * */
        @RequestMapping(value="/testParamsAndHeader",params = {"username","age!=10"},headers = {})
        public String testParamsAndHeader() {
            System.out.println("testParamsAndHeader");
            return SUCCESS;
        }
    
    @RequestMapping还支持Ant格式通配符
    Ant格式通配符.png

    3.PathVariable

    映射URL绑定的占位符


    映射URL绑定的占位符.png
    @PathVariable 用例:
        /*
        * @PathVariable 可以来映射URL中的占位符到目标方法的参数中
        * @param id
        * */
        @RequestMapping("/testPathVariable")
        public String testPathVariable(@PathVariable("id") Integer id) {
            System.out.println("testPathVariable: " + id);
            return SUCCESS;
        }
    

    4.@RequestParam

    使用@RequestParam绑定请求参数。

    • 在处理方法入参处使用@RequestParam可以把请求参数传递给请求方法
      -value:参数名
      -required:是否必须。默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常
    测试用例:
    SpringMVCTest.java中添加。
    /*
        * @RequestParam
        * -value:参值即请求参数的数名
        * -required:是否必须。默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常
        * -defaultValue:请求参数的默认值
        * */
        @RequestMapping(value = "/testRequestParam")
        public String testRequestParam(@RequestParam(value = "username") String username,
                                       // 此处 age 如果是 int 型变量,就必须设置 defaultValue="0"
                                       @RequestParam(value = "age",required = false) Integer age) {
            System.out.println("testRequestParam,uaername: " + username + " age:" + age);
            return SUCCESS;
        }
    -----------------------------------------------------------------
    index.jsp:
    <a href="springmvc/testRequestParam?username=myName&age=19">Test Rest GET</a><br>
    

    5.@RequestHeader

    绑定请求头的属性值

    • 请求头包含了若干个属性,服务器可根据此获知客户端的信息,通过@RequestHeader即可将请求头中的属性值绑定到处理方法的入参中
    用例:
    /*
        * 映射请求头信息
        * 用法同@RequestParam
        * */
        @RequestMapping(value = "/testRequestHeader")
        public String testRequestHeader(@RequestHeader(value = "User-Agent") String ua) {
            System.out.println("testRequestHeader,User-Agent: " + ua);
            return SUCCESS;
        }
    ------------------------------------------------------------------
    index.jsp:
    <a href="springmvc/testRequestHeader">testRequestHeader</a><br>
    

    6.@SessionAttributes

    如果希望在多个请求之间共享某个模型属性数据(学习笔记3中会讲到),则可以在控制类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中

    HttpSession.png

    示例:

    SpringMVCTest.java 添加:
    
    注意(***): 在 SpringMVCTest 类的上面添加:
               @SessionAttributes(value = {"user"},types = {String.class})
    
    /*
        * @SessionAttributes除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
        *                   还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
        * 注意:该注解只能使用在类的上面,为不能修饰方法
        * */
        @RequestMapping("/testSessionAttributes")
        public String testSessionAttributes(Map<String,Object> map) {
            User user = new User("Tom","123456","tom@qq.com",15);
            map.put("user",user);
            map.put("school","xztywss");
            return SUCCESS;
        }
    
    index.jsp添加:
    <a href="springmvc/testSessionAttributes">Test SessionAttributes</a><br>
    
    success.jsp添加:
    
        request user: ${requestScope.user }  <br><br>
    
        session user: ${sessionScope.user }  <br><br>
    
        request school: ${requestScope.school }  <br><br>
    
        session school: ${sessionScope.school }  <br><br>
    

    7.ModelAttribute

    • 先上示例:
    User.java添加属性(getter、setter、toString相应的改变(此处改变后不包括Address属性)):
    private Integer id;    
    
    注意:请添加一个不包含Address但是包含id的构造方法,同时应该有一个空的构造方法,不然有可能会出错。
    
    SpringMVCTest.java添加:
    /*
        * 有 @ModelAttribute 标记的方法会在每个目标方法被调用之前被 SpringMVC 调用!
        * */
        @ModelAttribute
        public void getUser(@RequestParam(value = "id",required = false) Integer id,
                            Map<String,Object> map) {
            if(id != null) {
                //模拟从数据库中获取对象
                User user = new User(1,"Tom","123456","tom@qq.com",12);
                System.out.println("从数据库中获取一个对象: " + user);
    
                map.put("user",user);
            }
        }
    
        @RequestMapping(value = "/testModelAttribute")
        public String testModelAttribute(User user) {
            System.out.println("修改: " + user);
            return SUCCESS;
        }
    
    index.jsp 添加:
    <!--
          模拟修改操作
          1.原始数据:1,Tome,123456,tom@qq.com,12
          2.密码不能被修改
          3.表单回显,模拟操作直接在表单填写对应的属性值
       -->
      <form action="springmvc/testModelAttribute" method="post">
          <input type="hidden" name="id" value="1">
    
          username: <input type="text" name="username" value="Tom"/>
          <br>
          email: <input type="text" name="email" value="tom@qq.com"/>
          <br>
          age: <input type="text" name="age" value="12"/>
          <br>
          <input type="submit" value="Submit">
      </form>
    
    • 输出:
    不包含@ModelAttribute注解的getUser()方法时的运行结果:
    修改: User{id=1, username='Tom', password='null', email='tom@qq.com', age=123}
    
    包含@ModelAttribute注解的getUser()方法时的运行结果:
    从数据库中获取一个对象: User{id=1, username='Tom', password='123456', email='tom@qq.com', age=12}
    修改: User{id=1, username='Tom', password='123456', email='tom@qq.com', age=13}
    
    注:主要区别在于password回显上的区别
    
    • 分析
    /*
        * 运行流程:
        * 1.执行 @ModelAttribute 注释修饰的方法:从数据库中取出对象,把对象放入 Map 中。键为:user
        * 2.SpringMVC 从 Map 中取出 User 对象,并把表单的请求参数赋给 User 对象的对应属性。
        * 3.SpringMVC 把上述对象传入目标方法的参数
        *
        * 注意:在 @ModelAttribute 修饰的方法中,放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致
        * */
    SpringMVC 确定目标方法 POJO 对象类型入参的过程 
    1.确定一个 key:
        1).若目标方法的 POJO 类型的参数没有使用@ModelAttribute 作为修饰,则 key 为 POJO 类名的第一个字母小写
        2).若使用了 @ModelAttribute 注解,则 key 为 @ModelAttribute 注解的 value 值
    2.在 implicitModel 中查找 key 对应的对象,若存在,则作为入参传入
        1).若在 @ModelAttribute 标记的方法中在 Map 中保存过,且 key 和 1 确定的 key 一致,则会获取到
    3.若 implicitModel  中不存在 key 对应的对象,则检查当前 Handler 是否使用 @SessionAttributes 注解修饰,
    若使用了该注解,且 @SessionAttributes 注解的 value 属性值中包含了 key,则会从 HttpSession中获取 key 所
    对应的 value值,若存在则直接传入到目标方法的入参中。若不存在则抛出异常。
    4.若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key ,则会
    通过反射来创建 POJO 类型的参数,传入为目标方法的参数
    5.SpringMVC 会把 key 和 POJO类型的对象保存到 implicitModel 中,进而会保存到 request 中。
    
    

    相关文章

      网友评论

        本文标题:SpringMVC学习笔记2(注解)

        本文链接:https://www.haomeiwen.com/subject/sihugqtx.html