• SpringMVC入门学习(二)


    SpringMVC入门学习(二)

    在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作。

    model.addAttribute()的使用

    model接口的源代码:

    由图可知,在addAttribute()中有两种入参方式,一种是指明名字var1,一种是不指明名字var1。在不指明名字中,会通过相近的去寻找。

    在addAttribute()中,我们可以放任何对象:

    首先先导入jsp标签maven相关的库

    <!--servlet导入-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <!--标签库的导入-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    

    controller里面的代码

    @RequestMapping("bye")
    public String bye(Model model){
        // 放list
        List<String> byeList = new ArrayList<>();
        byeList.add("小明");
        byeList.add("小红");
        byeList.add("小方");
        model.addAttribute("byeList",byeList);
        //  放Map
        Map<String,String> map= new HashMap<>();
        map.put("one","第一个");
        map.put("two","第二个");
        map.put("three","第三个");
        map.put("four","第四个");
        model.addAttribute("map",map);
        //  放对象bean
        User user = new User();
        user.setAge("18");
        user.setName("帅哥");
        model.addAttribute("user",user);
    
        return "bye";
    }
    

    jsp里面的使用

    放List <br>
    <c:forEach  items="${byeList}" var="bye">
        ${bye}<br>
    </c:forEach>
    
    放map <br>
    ${map.one}<br>
    ${map.two}<br>
    ${map.three}<br>
    ${map.four}<br>
    
    放对象bean <br>
    ${user.age} <br>
    ${user.name} <br>
    

    转发与重定向

    这位博主的例子写的挺好的博客地址

    假设你去办理某个执照,

    重定向:你先去了A局,A局的人说:“这个事情不归我们管,去B局”,然后,你就从A退了出来,自己乘车去了B局。

    转发:你先去了A局,A局看了以后,知道这个事情其实应该B局来管,但是他没有把你退回来,而是让你坐一会儿,自己到后面办公室联系了B的人,让他们办好后,送了过来。

    • 转发forward:
      服务器内部的操作,服务器去请求目标地址的URL【同一个WEB下面的组件】,然后读取返回结果,并将其发送给浏览器。所以在客户端看来,地址栏是没有变化的。
      【转发页面和转发到的页面能够共享数据
    • 重定向redirect:
      重定向是客户端的操作,服务器告诉浏览器要去哪个网址,然后浏览器进行跳转,然后浏览器的地址栏就是跳转的网址。
      不能共享数据

    重定向

    1. 不带参数的重定向

      /**
      * 不带重定向到请求网址
      * @param model
      * @return 重定向的网址: /bye
      */
      @RequestMapping("redirect0")
      public String redirect1(Model model){
          return "redirect:/bye";
      }
      
    2. 带参数的重定向
      (1)使用addAttribute进行字符串拼接

      /**
      *  带参数
      * @param attributes
      * @return 请求的网址是: /mian1?name=bird
      */
      @RequestMapping("redirect1")
      public String redirect1(RedirectAttributes attributes){
          attributes.addAttribute("name","bird");
          return "redirect:main1";
      }
      

      controller写法:

      @RequestMapping("main1")
      public String main1(@RequestParam("name") String name, Model model){
          //通@RequestParam过获得name数据
      
          model.addAttribute("name",name);
          return "redirect";
      }
      

      (2)使用addFlashAttribute

      /***
      *  
      *
      */
      @RequestMapping("redirect2")
      public String redirect2(RedirectAttributes attributes){
          /*
          * 此时请求的网址是:/mian2
          * addFlashAttribute()是将数据放在session里面,但是session在页面跳转时,会马上移除。
          */
          attributes.addFlashAttribute("name","xiaohuiFlash");
          return "redirect:main2";
      }
      

      controller的写法:

      /* 与addAttribute不同的是,他是通过@ModelAttribute获得数据
      *  
      */
      @RequestMapping("main2")
      public String main2(@ModelAttribute("name") String name, Model model){
          model.addAttribute("name",name);
          return "redirect";
      }
      

    转发

    在Springmvc中请求是默认转发到jsp中的【可以省略forward】,例如:

    @RequestMapping("hello")
    public String hello(Model model){
        model.addAttribute("hello","世界");
        return "hello";
    }
    

    此时是自动转发到:/WEB-INF/jsp/hello.jsp【路径设置问题在上一篇提到过】,当然如果文件不在jsp文件夹中,则可以指令路径,如:return "forward:WEB-INF/index/index.jsp"

    如果要转发到controller上,则必须加上forward:

    @RequestMapping("hello")
    public String hello(Model model){
        model.addAttribute("hello","世界");
        // 转发到:/bye 的controller上面
        return "forward:bye";
    }
    

    关于请求路径的问题

    在Springmvc中支持ant风格的路径,其中ANT通配符有三种:

    通配符说明
    ? 匹配任意一个字符【不能为空,不能为/】
    * 匹配0个或则任意个字符
    ** 匹配0或则多个目录

    例子:

    URL路径说明
    /index?/get 可以为/index1/get,/index2/get,但是不能为/index/get
    /index*/get 可以为/index1/get,/indexa1/get,也可以为/index/get
    /index/**/get 可以为/index/one/get,/index/one/two/get,也可以为/index/get

    其中,会根据最长匹配原则(has more characters)来进行匹配,例如:

    /jsp/index/.jsp和/jsp/**/.jsp会优先匹配第一个

    Springmvc设置字符编码过滤器

    在web.xml的配置文件中:

    <!-- characterEncodingFilter字符编码过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <!-- 需要使用的字符集 -->
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <!--是否强制设置request的编码为encoding,即UTF-8,默认为false -->
            <param-name>forceRequestEncoding</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <!--是否强制设置response的编码为encoding,即UTF-8 -->
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!-- 这里必须写 /* -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    

    注意:此时是设置默认的编码方式,也即是说,可以在自己写的代码中重新指令编码方式。

    关于静态资源放行的问题

    由于我们经Servlet设置的URI匹配模式是:/,所以,它将静态资源js,css等等也当成了一个后台请求从而导致404错误。

    最简单的解决方法,在Spring配置文件中

    <!-- 他将在Spring上下文中定义一个DefaultServletHttpRequestHandler来处理静态资源,实际上就是将转发给默认的servlet -->
    <mvc:default-servlet-handler/>
    

    但是此时会发现又会出现一个问题,那就是@RequestMapping("/path")不能访问,这时候再配置文件中再添加一句代码

    <!-- 原因是因为当没有mvc:default-servlet-handler时,框架默认注册AnnotationMethodHandlerAdapter可以处理@RequestMapping,而当加入时,就没有了,这时候加入mvc:annotation-driven就会注册一个AnnotationMethodHandlerAdapter -->
    <mvc:annotation-driven/>
    

    关于form表单提交数据的方式

    • 方式一:直接将表单参数卸载Controller相应的方法的形参中。
      前端表单

      <form action="/form" method="post">
          <input type="text" name="name"><br>
          <input type="password" name="pwd"><br>
          <input type="submit" value="提交">
      </form>
      
      @RequestMapping("/form")
      后端接受数据
      public String getForm(String name,String pwd){
          /**
          * 在形参中,name和pwd要一一对应
          * @param name
          * @param pwd
          * @return
          */
          System.out.println("名字:"+name);
          System.out.println("密码:"+pwd);
          return "";
      }
      
    • 方式二:使用HttpServletRequest接受数据

      @RequestMapping("/form")
      public String getForm(HttpServletRequest request){
          System.out.println("名字是"+request.getParameter("name"));
          System.out.println("密码是"+request.getParameter("pwd"));
          return "";
      }
      
    • 通过一个Bean来接受数据【适合大量数据的情况】
      建立一个UserBean

      public class User {
          private String name;
          private String pwd;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getPwd() {
              return pwd;
          }
      
          public void setPwd(String pwd) {
              this.pwd = pwd;
          }
      }
      

      这时候就可将形参改为User了,注意User必须保留默认的构造方法

      @RequestMapping("/form")
      public String getForm(User user){
          System.out.println("名字是"+user.getName());
          System.out.println("密码是"+user.getPwd());
          return "";
      }
      
    • 使用注解@RequestParam绑定请求参数到方法入参

      @RequestMapping("/form")
      public String getForm(@RequestParam("name")String name,@RequestParam(value = "pwd")String pwd){
          System.out.println("名字是"+name);
          System.out.println("密码是"+pwd);
          return "";
      }
      

      当然这时候,如果请求的数据没有pwd,比如说请求的数据是:/form?name=one,那么程序便会报错

      13-Nov-2018 02:00:11.459 警告 [http-nio-8080-exec-9] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'pwd' is not present]
      

      这时候可以设置@RequestParam的属性required为false

      //此时要将value补上,同时可以设置defaultValue 也就是默认值
      @RequestParam(value = "name",required=false)   
      
      @RequestParam(value = "name",required=false,defaultValue="0")String name   
      
    • 使用@PathVariable获得路径的参数

      @RequestMapping("/form1/{name}/{pwd}")
      public String form1(@PathVariable String name,@PathVariable String pwd){
          System.out.println("使用@");
          System.out.println("名字是"+name);
          System.out.println("密码是"+pwd);
          return "";
      }
      

      这时候如果访问http://localhost:8080/form1/one/two使,那么one将绑定在name上,two将绑定在pwd上面。

      输出结果:

      名字是one
      密码是two
      

    关于时间日期提交的问题

    当我们的数据库中含有Data类型的数据时,因为form表单提交的是String类型,而在SpringMVC中无法自动的将String类型的转为Data类型,从而无法将数据写入实体类和数据库。解决方法如下:

    • 使用@DateTimeFormat注解

      // 实体类UserDate,在Date上面加上注解
      @DateTimeFormat(pattern = "yyyy-MM-dd")
      private Date date;
      

      Controller类不需要有任何变化

      @RequestMapping("/formData")
      public String formData(UserDate userData) {
          return "";
      }
      
    • 使用@InitBinder注解
      @InitBinder用于在@Controller中标注于方法,表示为当前控制器注册一个属性编辑器或者其他,只对当前的Controller有效。

      // 这个方法会在控制器中其他方法之前调用,这样就可以预先处理数据
      @InitBinder
      public void InitBinder(WebDataBinder binder){
          DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
          // 第二个参数表示是否允许为空
          CustomDateEditor dateEditor = new CustomDateEditor(format,true);
          //注册自定义的日期转换格式
          binder.registerCustomEditor(Date.class,dateEditor);
      }
      

    天地有正气,杂然赋流形。下则为河岳,上则为日星。于人曰浩然,沛乎塞苍冥。

  • 相关阅读:
    win10+Linux双系统安装及一些配置问题
    第3讲--3.1旋转矩阵
    【读诗】宣州谢朓楼饯别校书叔云
    【2】python:end=' '
    如何与国外导师联系
    PointNet
    点云深度学习
    ES6常用方法
    监听滚动条、上下联动
    echarts 左右滚动
  • 原文地址:https://www.cnblogs.com/xiaohuiduan/p/9953747.html
Copyright © 2020-2023  润新知