SpringMVC入门学习(二)

SpringMVC入门学习(二)

ssm框架 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);
    }
    

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

原文地址:https://www.cnblogs.com/xiaohuiduan/p/9953747.html

时间: 2024-11-01 21:55:30

SpringMVC入门学习(二)的相关文章

Objective C 快速入门学习二

Objective-C 类.对象.方法 1.编写一个复数类: #import <Foundation/Foundation.h>@interface Complex: NSObject //类声明,Complex继承NSObject { int iReal;//成员变量声明,在括号内 int iImag; } //成员函数声明,在括号外 -(void) print; -(void) setReal : (int) n; -(void)setImag : (int) d; @end //@int

MongoDB入门学习(二):MongoDB的基本概念和数据类型

上一篇讲了MongoDB的安装和管理,其中涉及到了一些概念,数据结构还有一些API的调用,不知道的没关系,其实很简单,这篇会简单介绍一下. 1.文档 文档是MongoDB的核心概念,多个键值对有序的放在一起就是一个文档,文档是MongoDB存储数据最基本的数据结构.对MongoDB都是以文档的形式来操作的,使用了一种类似JSON的二进制BSON数据格式,对API的调用都是传的文档参数.每种编程语言都有标示文档的数据结构,比如java的map,lua的table,python的dict等等,但是都

git入门学习(二):新建分支/上传代码/删除分支

一.git新建分支,上传代码到新的不同分支 我要实现的效果,即是多个内容的平行分支:这样做的主要目的是方便统一管理属于同一个内容的不同的项目,互不干扰.如图所示: 前提是我的github上已经有webpack_test项目了,我是在这个项目的基础上新建其他的分支并开展工作的.如图: 如果你对如何新建webpack_test项目不清楚,请参考我的前一篇文章:git入门学习(一):github for windows上传本地项目到github,操作步骤如下: 1.1.保留webpack_test项目

activiti入门学习二

一.上一篇入门学习的地址 https://www.cnblogs.com/yangk1996/p/10878449.html 二.单机演示Demo 12.使用UEL表达式动态增加流程处理人 从新创建一个流程,使其Assignee变成表达式的.然后从新创建流程. * @Description: 启动流程实例,动态设置assignee * @date: 2019/6/23 20:28 */ public class AssigneeUel { public static void main(Stri

SpringMVC入门学习(二)应用注解方式+注解优化

前篇已经介绍使用SpringMVC的方式进行环境搭建,以及一个简单的demo测试,下面我们再来介绍一下使用注解的方式,如何实现. 添加配置文件 springAnnotation-servlet.xml <!-- 注解扫描包 --> <context:component-scan base-package="com.tgb.web.controller.annotation" /> <!-- 开启注解,这两种方式通用 --> <!-- <b

SpringMVC入门学习(一) 环境搭建+实例演示

简单介绍SpringMVC SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回. DispatcherServlet是继承自HttpServlet的,既然SpringMVC是

node入门学习(二)

一.模块系统 1.创建模块和引用模块 //如何创建一个模块 exports.hello = function(){ console.log('hello worl'); }; //这创建了一个模块 //如何引用模块 //1.require(); var hello = require('./module.js'); hello.hello(); //2. var {hello} = require('./module.js'); hello(); 2.服务端的模块 //服务端的模块 var ht

SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器

一.参数的传递 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica } 1.简单的参数传递 1 /* @RequestParam用法:入参名字与方法名参数名不一致时使用{ 2 * value:传入的参数名,required:是否必填,defaultValue:默认值 3 * } 4 */ 5 @RequestMapping("itemEdit") 6 public ModelAndView itemEdit(@R

java入门学习(二)

一.类和对象 1.开篇瞎BB 物以类聚. 世间万物皆对象,对象是能接触到的实体.类是一组有相同属性和方法的对象的集合,或者说它们的特征提取,类是一种抽象的概念.类由属性和方法组成,属性是它的各种静态的特征,方法是它能干啥.<易>有云,“物以类聚,人以群分”. 打个比喻,有一群人都在追一个很可爱的姑娘.这群人可以抽象出一个类,他们有相同的属性,比如都喜欢这姑娘,都是男孩子.他们有一些相同的方法,什么送花儿呀,请吃饭呀,请看电影呀,陪姑娘聊天呀.所以呀,他们是一个类.而单独的一个人就是一个对象,这