SpringMVC获得请求数据
获得基本类型参数
先写上控制器方法
@RequestMapping("/quick9")
@ResponseBody//不进行页面跳转
public void save9(String username,int age){
System.out.println(username);
System.out.println(age);
}
然后从浏览器端发送请求:
在服务器端控制台可看到浏览器端发送过来的请求参数:
获得POJO(普通JavaBean类型)类型参数
Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配。
@RequestMapping("/quick10")
@ResponseBody//不进行页面跳转
public void save10(User user){
System.out.println(user.getUsername());
System.out.println(user.getAge());
}
访问:
结果:
获得数组类型参数
@RequestMapping("/quick11")
@ResponseBody//不进行页面跳转
public void save11(String[] strs){
System.out.println(Arrays.asList(strs));
}
请求一下就行,自己测。
获得集合类型参数
集合类型参数的封装要比数组要麻烦一点,数组直接在方法上写个数组的形参只要名称一致就可以封进去,但是集合不行(目前不行),它需要借助一个VO对象进行封装,这也是第一种方式。
啥是VO对象?
ValueObject值对象,就是帮我们封装数据用的一个对象
所以我们现在在domain包下写上一个VO对象
为了方便测试写一个表单提交。
控制器中打印一下传输过来的数据:
@RequestMapping("/quick12")
@ResponseBody//不进行页面跳转
public void save12(VO vo){
System.out.println(vo);
}
测试一下即可。
第二种方式:
当视同ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装。
@RequestMapping("/quick12")
@ResponseBody//不进行页面跳转
public void save12(@RequestBody List<User> userList){
System.out.println(userList);
}
请求参数乱码问题
<!--配置全局过滤的filter-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>CharacterEncodingFilter</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
而且学到现在总结出一条规律可以记着,就是对web项目全局的配置操作就应该写在web.xml的配置文件中(比如上面写的全局的乱码问题、全局页面调控的前端控制器,还有在web项目启动时加载Spring容器等),而框架的配置文件就全部放在resources根目录中。
参数绑定注解@requestParam
为什么需要这个注解?我们看下面的情况:
我们在控制器中写上需要页面传来一个String类型的字符串参数username
@RequestMapping("/quick13")
@ResponseBody//不进行页面跳转
public void save13(String username){
System.out.println(username);
}
然后访问
控制台上显示成功
但是问题出现了,这是页面准确写出了username这个形参,但是如果写错了的话就会出错,显示参数null。为了解决这个可能拼写错误的原因,出现了@requestParm注解。
如上图所示,如果请求参数发来的是name,则可以写上@RequestParm(value=“name”)进行与username的绑定。
@RequestMapping("/quick13")
@ResponseBody//不进行页面跳转
public void save13(@RequestParam(value="name") String username){
System.out.println(username);
}
现在使用name参数进行访问就可以获得值了。
除了value值以外,@RequestParm注解还有其他参数:
required:此在指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错
解释:
这个参数默认情况是true,意思就是不改成false的话那么对该控制器方法进行访问时则必须携带上这个参数,否则报404页面访问错误。
@RequestMapping("/quick13")
@ResponseBody//不进行页面跳转
public void save13(@RequestParam(value="name") String username){
System.out.println(username);
}
改成false以后,不报错,但是只会传来null值:
@RequestMapping("/quick13")
@ResponseBody//不进行页面跳转
public void save13(@RequestParam(value="name",required = false) String username){
System.out.println(username);
}
defaultValue:当没有指定请求参数时,则使用指定的默认值赋值。
意思就是:如果客户端没有穿来指定的参数值的话,则默认将defaultValue的值赋值给控制器方法的参数:
@RequestMapping("/quick13")
@ResponseBody//不进行页面跳转
public void save13(@RequestParam(value="name",required = false,defaultValue = "haha") String username){
System.out.println(username);
}
访问没有参数:
控制台默认打印haha:
获得Restful风格的参数
比如上图中,我们在浏览器地址栏访问如上,/quick19/zhangsan,这就是Restful风格的参数,对应的我们就会在控制器层方法中写上对应的路由风格:/quick19/{name},其中{name}就是占位符,对应了地址栏中的zhangsan值。然后我们就可以使用@PathVariable对该占位符进行解析,赋值给方法中的形参。
@RequestMapping("/quick15/{name}")
@ResponseBody//不进行页面跳转
public void save15(@PathVariable(value="name") String name){
System.out.println(name);
}
自定义类型转换器(不是很重要,大概看看叭)
用日期类型的数据演示一下步骤
先写一个转换器类实现Converter接口,内部写上逻辑转换的方法,其中Converter<String,Date>带了泛型,前面的String是浏览器端传来的字符串,而后面的Date就是指定的要转换的类型。
然后在spring-mvc的配置文件中进行配置,告诉SpringMVC。
最后在<annotation-driven>中引用转换器。
获得Servlet相关API(了解一下)
有个小知识点可以提一下,就是控制器中的方法虽然是我们定义的,但调用者都是框架调用的。
获得请求头(用的不多)
文件上传(原始方式)
先复习一下原始web阶段上传文件的操作流程:
单文件上传步骤
1、导入fileupload和io坐标
<!--导入文件上传的插件-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
2、配置文件上传解析器
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--上传文件的字符编码-->
<property name="defaultEncoding" value="UTF-8"></property>
<!--最大上传文件大小-->
<property name="maxUploadSize" value="500000"></property>
</bean>
3、编写文件上传代码
编写文件上传代码时,文件上传到控制器方法时SpringMVC会帮我们把这个文件封装成一个对象:MultipartFile,这个对象的参数名必须与文件上传表单中的name值一致。
如下图中的文件值name叫uploadFile,那么控制器方法中的形参名也得叫uploadFile
在web层下面写上一个upload.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/quick16" method="post" enctype="multipart/form-data">
name:<input type="text" name="username"><br>
文件:<input type="file" name="uploadFile"><br>
<input type="submit" name="提交">
</form>
</body>
</html>
编写对应的控制器方法:
@RequestMapping("/quick16")
@ResponseBody//不进行页面跳转
public void save16(String username, MultipartFile uploadFile){
System.out.println(username);
System.out.println(uploadFile);
}
现在试着访问并打印一下是否有结果:
点击提交之后将会自动由路径跳转到控制器方法quick16:
然后控制台可以看到输出信息:
但是现在我们要将浏览器上传过来的文件进行保存,所以控制器方法应该写成下面这样:
@RequestMapping("/quick16")
@ResponseBody//不进行页面跳转
public void save16(String username, MultipartFile uploadFile) throws IOException {
//这是输出表单中的所传过来的第一个参数值:username
System.out.println(username);
//获得上传文件名称
//获得上传文件名称我们肯定会用到这个封装好的对象uploadFile对叭?
// uploadFile.getName();注意获得上传文件名称不是调用这个方法
// 这个方法获得的是该上传文件的表单项的名称:uploadFile
//下面这个originalFileName才是我们要用的
String originalFilename = uploadFile.getOriginalFilename();
/*
接下来就要存了,用io的知识也可以,但是这里框架提供了更为简便的方法,所以我们使用
框架提供的东西:封装好的对象uploadFile.transferTo():将文件存到哪里去
该方法内部需要一个File对象,所以我们new一个放进去
File()当中需要给一个保存该文件的地址,真正的开发当中里面肯定写的是一个服务器的地址
但是我们这里只是学习,所以不用那么高级。就写本地磁盘就可以了
这里我在桌面创建了一个upload空文件,看一会儿是否能保存进去叭
*/
uploadFile.transferTo(new File("C:\\Users\\爱闹的蹦蹦\\Desktop\\upload\\"+originalFilename));
}
启动访问:
点击提交后跳转到quick16
控制台输出表单的第一项username
然后我们去upload文件中查看是否已被保存下来:
保存成功。
多文件上传
其实都一样,我们现在试着上传两个file文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/quick16" method="post" enctype="multipart/form-data">
name:<input type="text" name="username"><br>
文件一:<input type="file" name="uploadFile"><br>
文件二:<input type="file" name="uploadFile2"><br>
<input type="submit" name="提交">
</form>
</body>
</html>
注意控制器方法中的参数名要与表单项中的文件名相匹配。
@RequestMapping("/quick16")
@ResponseBody//不进行页面跳转
public void save16(String username, MultipartFile uploadFile,MultipartFile uploadFile2) throws IOException {
//这是输出表单中的所传过来的第一个参数值:username
System.out.println(username);
//获得上传文件名称
//获得上传文件名称我们肯定会用到这个封装好的对象uploadFile对叭?
// uploadFile.getName();注意获得上传文件名称不是调用这个方法
// 这个方法获得的是该上传文件的表单项的名称:uploadFile
//下面这个originalFileName才是我们要用的
String originalFilename = uploadFile.getOriginalFilename();
/*
接下来就要存了,用io的知识也可以,但是这里框架提供了更为简便的方法,所以我们使用
框架提供的东西:封装好的对象uploadFile.transferTo():将文件存到哪里去
该方法内部需要一个File对象,所以我们new一个放进去
File()当中需要给一个保存该文件的地址,真正的开发当中里面肯定写的是一个服务器的地址
但是我们这里只是学习,所以不用那么高级。就写本地磁盘就可以了
这里我在桌面创建了一个upload空文件,看一会儿是否能保存进去叭
*/
uploadFile.transferTo(new File("C:\\Users\\爱闹的蹦蹦\\Desktop\\upload\\"+originalFilename));
//现在上传第二个文件
String originalFilename2 = uploadFile2.getOriginalFilename();
uploadFile2.transferTo(new File("C:\\Users\\爱闹的蹦蹦\\Desktop\\upload\\"+originalFilename2)));
}
具体访问过程就不演示了,一样的。
多文件上传也可以使用数组的形式:
总结
回忆回忆,得记熟且会操作。