零、 复习昨日
springmvc支持json数据交互,但是自己本身没有对应jar,使用的是第三方Jackson,只需要导入对应依赖,springmvc即可使用
如果需要换用到FastJson
- 导入依赖
- 配置文件中指定json转换的类型为FastJson
- 本次课程没有替换,用的还是Jackson
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.8version>
dependency>
只需要在方法上加
@ResponseBody
注解,即可将返回值变为JSON
需求: 前端发请求,后台响应给浏览器JSON
@Controller
public class JSONController {
@RequestMapping("/test1")
@ResponseBody // 返回JSON对象,不经过视图解析器
public String test1() {
System.out.println("响应json-test1" );
return "{\"code\":200,\"msg\":\"OK\"}";
}
}
前后端交互,一般固定一个JSON模板
模板一般要包含三个信息:
状态码
- 自定义的
- 每个意思都不一样
- 假如: 20000 成功 40000 资源未找到 50000 没有权限 60000 代码异常…
提示信息
数据
{ code:20000, msg:"查询成功", data:{ id:1, username:"张三" } }
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 封装的结果数据
* --> 符合layui默认模板格式
* {
* "code": 0,
* "msg": "",
* "count": 1000,
* "data": [{}, {}]
* }
*/
public class ResultData {
private int code; // 0是成功,其他都是不成功
private String msg;
private int count;
private Object data;
public ResultData() {
}
public static ResultData ok() {
ResultData resultData = new ResultData( );
resultData.setCode(0);
resultData.setMsg("成功");
return resultData;
}
public static ResultData ok(Object data) {
ResultData resultData = new ResultData( );
resultData.setCode(0);
resultData.setMsg("成功");
resultData.setData(data);
return resultData;
}
public static ResultData ok(Object data,int count) {
ResultData resultData = new ResultData( );
resultData.setCode(0);
resultData.setMsg("成功");
resultData.setData(data);
resultData.setCount(count);
return resultData;
}
public static ResultData fail() {
ResultData resultData = new ResultData( );
resultData.setCode(-1);
resultData.setMsg("失败");
return resultData;
}
// set get 省略,自己加
}
Controller方法只需要将返回值类型变为对应的类型
@RequestMapping("/test2")
@ResponseBody // 返回JSON对象,不经过视图解析器
public ResultData test2() {
System.out.println("响应json-test2" );
return ResultData.ok();
}
@RequestMapping("/test3")
@ResponseBody
public ResultData test3() {
System.out.println("响应json-test3" );
// 模拟查询全部
List<User> list = new ArrayList<>( );
for (int i = 1; i < 10; i++) {
User user = new User( );
user.setId(i);
user.setUsername("测试"+i);
user.setScore(i * 33.3);
user.setBirthday(new Date(i * 24 * 60 * 60 * 1000));
list.add(user);
}
return ResultData.ok(list);
}
如果类中所有方法都需要返回成JSON,即都要加@ResponseBody,那么就可以将
类上加
@ResponseBody,方法上不需要加注解
其实还有一个类似的注解
@RestController
,相对于是@Controller和@ResponseBody综合版这是RESTful开发风格的写法
前端使用ajax发送json数据,后端使用
简单类型(基本类型,String,Date)来直接接收
<button id="btn1">btn1-ajax-json-简单类型button>
<script src="/js/jquery-2.1.0.js">script>
<script>
$("#btn1").click(function (){
$.ajax({
url:"/test4.do",
type:"get",
data:{"id":1,"username":"张三"},
success:function (ret){
if (ret.code == 0){
alert(ret.msg)
}
},
error:function (){
alert("服务器正忙!")
}
})
});
script>
/**
* 接收JSON数据
*/
@RequestMapping("/test4")
public ResultData test4(int id,String username){
System.out.println("id = " + id);
System.out.println("username = " + username);
return ResultData.ok();
}
前端使用ajax发送json数据,后端使用对象来接收
【特别注意】:
其实真正发送数据到后台时是按照表单内容发送,所以后端可以直接用对象接收!
为什么data为json格式的数据,还是会以表单内容发送呢?是因为ajax的contentType默认是application/x-www-form-urlencoded
即,如果真的要发送完全的JSON数据,就需要指定contentType=
"application/json"
,但是此时后台就没有办法直接使用对象接收数据
【总结】:
请求方式是GET的话,contentType指定成什么类型,后台都可以直接用对象接收
请求方式是POST的,contentType=“application/x-www-form-urlencoded”(默认),后台也可以使用对象接收
前端ajax请求方式是POST的,contentType="application/json"时,发送的数据data内容需要
变成json字符串才行,否则后台
就不能使用对象直接接收,需要使用@RequestBody
来解析JSONdata:JSON.stringify({“id”:1,“username”:“admin”})
<button id="btn2">btn2-ajax-json-对象类型button>
<script src="/js/jquery-2.1.0.js">script>
<script>
$("#btn2").click(function (){
$.ajax({
url:"/test5.do",
type:"post",
data:{"id":1,"username":"张三","score":98.0,"birthday":"2022-12-12"},
// contextType:"application/json",
success:function (ret){
if (ret.code == 0){
alert(ret.msg)
}
},
error:function (){
alert("服务器正忙!")
}
})
});
script>
public class User {
private int id;
private String username;
private double score;
// 日期,默认只能解析yyyy/MM/dd类型的日期,如果前端就是yyyy-MM-dd
// 那么就需要使用该注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
// set get...
}
@RequestMapping("/test5")
// 后台直接使用User对象来接收,JSON的key要与User的属性一致
public ResultData test5(User user){
System.out.println("user = " + user);
return ResultData.ok();
}
前端发送json数据,后台如果使用简单类型接收单独参数,正常接收
前端发送json数据,后台如果使用对象接收,可以尝试使用对象直接接收
如果对象内没有数据,可以使用@RequestBody来解析json,将数据封装到对象
使用第三方(commons-io,commons-fileupload)依赖
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.4version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.3version>
<exclusions>
<exclusion>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
exclusion>
exclusions>
dependency>
springmvc配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="102400"/>
bean>
页面
<form action="/upload.do" method="post" enctype="multipart/form-data">
文件上传<input type="file" name="source"><br>
<input type="submit" value="上传">
form>
后端
/**
* 文件上传(存储到tomcat服务)
* @param source 类型必须是MultipartFile,参数名必须是和前端name值一样
* 这样,文件上传时,MultipartFile内部就会有文件对象
* @param request 通过请求对象可以获得服务器地址,后续讲图片上传到服务对应位置
* @return
*/
@RequestMapping("/upload")
public String upload(MultipartFile source, HttpServletRequest request) throws IOException {
String originalFilename = source.getOriginalFilename( );
System.out.println("originalFilename = " + originalFilename);
// 产生随机图片名
String prefix = UUID.randomUUID( ).toString( );
System.out.println("prefix = " + prefix);
// 获得文件后缀
String suffix = FilenameUtils.getExtension(originalFilename);
// 组合成新文件名
String filename = prefix+"."+suffix;
// 获得服务器路径
String realPath = request.getServletContext( ).getRealPath("/upload_file");
System.out.println("realPath = " + realPath);
// 创建文件夹
File parentFile = new File(realPath);
if (!parentFile.exists()) {
parentFile.mkdir();
}
// 开始上传
source.transferTo(new File(parentFile,filename));
return "ok";
}
方案一(同步): 上传成功后,将图片路径返回给前端,前端再处理
方案二(异步): 使用ajax上传,上传成功后,将图片路径返回给ajax的回调函数
前端页面
<h1>上传图片并回显h1>
<form id="formData">
文件上传<input type="file" name="source"><br>
<input type="button" onclick="ajaxUpload()" value="上传">
form>
<img width="300px" id="img" src="" alt="图片">
<script src="/js/jquery-2.1.0.js">script>
<script>
// 文件上传
function ajaxUpload(){
// 获得表单对象
var formData = new FormData($("#formData")[0]);
// 使用ajax文件上传
$.ajax({
url:"/upload.do",
type:"post",
data:formData,
async:false,
cache:false,
contentType:false,
processData:false,
success:function (ret) {
if (ret.code == 0) {
console.log(ret.data)
$("#img").attr("src",ret.data);
}else{
alert("上传失败1");
}
},
error:function () {
alert("上传失败2");
}
});
}
script>
body>
html>
后端
// 与之前一样,只是将图片路径返回了,JSON格式的数据
return ResultData.ok("/upload_file/"+filename);
1 将来写项目,文件上传后,要将图片路径存储到数据库
2 等真正写项目时,一般要有文件服务器(阿里云OSS,七牛云存储等)
前端
<div>
<div>
<img width="300px" src="/upload_file/81d30e55-d6ca-4463-ba3b-5732504128f3.jpg">
<button>
<a href="/download.do?filename=81d30e55-d6ca-4463-ba3b-5732504128f3.jpg">下载a>
button>
div>
<div>
<img width="300px" src="/upload_file/dazhong.jpg">
<a href="/download.do?filename=dazhong.jpg">下载a>
div>
div>
后端
/**
* 下载图片
* 下载是需要响应一个对话框,选择文件下载到什么地方
* 不需要跳转页面,或者返回JSON
*/
@RequestMapping("/download")
public void download(String filename, HttpServletRequest request, HttpServletResponse response) throws IOException {
String realPath = request.getServletContext( ).getRealPath("/upload_file");
String filepath = realPath+"/"+filename;
//设置响应头 告知浏览器,要以附件的形式保存内容
//浏览器显示的下载文件名
response.addHeader("content-disposition","attachment;filename="+filename);
response.setContentType("multipart/form-data");
//读取目标文件,写出给客户端
IOUtils.copy(new FileInputStream(filepath),response.getOutputStream());
}
在Spring整合Mybatis基础上,再加上SpringMVC的配置即可
依赖
配置文件
1 web.xml定义监听器
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
2 springmvc和applicationContext.xml
springmvc.xml
<context:component-scan base-package="com.qf" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
applicationContext.xml
<context:component-scan base-package="com.qf">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
1 完成ssm整合,完成查询全部,分页模糊查询
2 复习mybatis ,复习项目