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:
重定向是客户端的操作,服务器告诉浏览器要去哪个网址,然后浏览器进行跳转,然后浏览器的地址栏就是跳转的网址。
【不能共享数据】
重定向
不带参数的重定向
/**
* 不带重定向到请求网址
* @param model
* @return 重定向的网址: /bye
*/
@RequestMapping("redirect0")
public String redirect1(Model model){
return "redirect:/bye";
}
带参数的重定向
(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来接受数据【适合大量数据的情况】
建立一个UserBeanpublic 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);
}
天地有正气,杂然赋流形。下则为河岳,上则为日星。于人曰浩然,沛乎塞苍冥。
SpringMVC入门学习(二)的更多相关文章
- ReactJS入门学习二
ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...
- SpringMVC入门学习(一)
SpringMVC入门学习(一) ssm框架 spring SpringMVC是一个Java WEB框架,现在我们知道Spring了,那么,何为MVC呢? MVC是一种设计模式,其分为3个方面 mo ...
- git入门学习(二):新建分支/上传代码/删除分支
一.git新建分支,上传代码到新的不同分支 我要实现的效果,即是多个内容的平行分支:这样做的主要目的是方便统一管理属于同一个内容的不同的项目,互不干扰.如图所示: 前提是我的github上已经有we ...
- Egg入门学习(二)---理解service作用
在上一篇文章 Egg入门学习一 中,我们简单的了解了Egg是什么东西,且能做什么,这篇文章我们首先来看看官网对Egg的整个框架的约定如下,及约定对应的目录是做什么的,来有个简单的理解,注意:我也是按照 ...
- SpringMVC入门学习三
今天是Springmvc学习的第三天,今天我将主要介绍一下: 常用注解的使用 关于非post.get请求的处理 文件上传与下载 拦截器 常用注解的使用 老大在此 @Controller @Cont ...
- SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器
一.参数的传递 1.简单的参数传递 /* @RequestParam用法:入参名字与方法名参数名不一致时使用{ * value:传入的参数名,required:是否必填,defaultValue:默认 ...
- node入门学习(二)
一.模块系统 1.创建模块和引用模块 //如何创建一个模块 exports.hello = function(){ console.log('hello worl'); }; //这创建了一个模块 / ...
- dubbo入门学习(二)-----dubbo hello world
一.dubbo hello world入门示例 1.提出需求 某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址: 我们现在需要创建两个服务模块进行测试: 模块 功能 订单服务web模块 创 ...
- springMVC入门(二)------springMVC入门案例
简介 本案例主要完成了springMVC的基本配置,可针对响应的HTTP URL返回数据与视图 一.###web.xml的配置 要使springMVC生效,首先需要对web.xml进行配置,配置spr ...
随机推荐
- 为docker配置HTTP代理服务器
背景: node1不能访问外网, node2可以访问外网,node1通过node2的代理服务来访问外网. 1. node1不能访问外网 vim /etc/resolv.conf 注释掉DNS配置文件 ...
- Hbase 性能改进
第一种性能改进方式:
- shell脚本中跳转另一台主机执行命令 <<EOF
ssh vmuser@ <<EOFmkdir /home/vmuser/xunjianrm /home/vmuser/xunjian/xj.logtouch /home/vmuser/xu ...
- Python12/25--前端之BOM/DOM
一.DOM 1. 什么是DOM 文档对象模型 Document Object Model 文档对象模型 是表示和操作 HTML和XML文档内容的基础API 文档对象模型,是W3C组织推荐的处理可扩展标 ...
- qhfl-1 跨域
CORS跨域请求 CORS即Cross Origin Resource Sharing 跨域资源共享,那么跨域请求还分为两种,一种叫简单请求,一种是复杂请求 简单请求 HTTP方法是下列方法之一 HE ...
- go的数据库操作mysql
go get github.com/go-sql-driver/mysql package main; import ( "database/sql" _ "github ...
- java_io
JAVA IO流(一)参考文章:http://ifeve.com/java-io-network/,并发编程网原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java ...
- Visual C++.NET设计
首先,创建对应的工程,VS2010以及以前的版本,创建项目时都可以在CLR下找到“Windows窗体应用程序”的项目模板,但是VS2012以后的版本就没这么方便了.可以通过打开旧版本的项目来修改,也可 ...
- 1.SpringMVC入门
创建一个web工程 导入jar 配置web.xml 在web.xml配置前端控制器:DispatcherServlet <?xml version="1.0" encodin ...
- [Project] MiniSearch文本检索简介
1. 预处理过程 预处理主要用来事先生成程序在运行过程中可能用到的数据,以便加速处理时间. 预处理的过程主要生成程序所需的三个文件:网页库文件,网页位置信息文件和倒排索引文件. 网页库文件 其中网页库 ...