1. 处理JSON数据
1.1 案例需求
目标: RoleConrtoller控制器
- /role/list GET请求
- 跳转到角色管理初始化页面 role_list.jsp
请求转发
- 跳转到角色管理初始化页面 role_list.jsp
- /role/data_list GET请求
Ajax
- 获取角色
数据
- 返回JSON格式的数据
- 获取角色
- /role/add GET请求
- 跳转到新增角色页面 role_add.jsp
请求转发
- 跳转到新增角色页面 role_add.jsp
- /role/add POST请求
- 保存成功后弹出成功提示,然后跳转到列表页面
Ajax
- 保存成功后弹出成功提示,然后跳转到列表页面
- /role/update/10 GET请求
- 跳转到用户修改页面 user_update.jsp
请求转发
- 跳转到用户修改页面 user_update.jsp
- /role/update POST请求
- 保存成功后弹出成功提示,然后跳转到列表页面
Ajax
- 保存成功后弹出成功提示,然后跳转到列表页面
- /role/delete/10 GET请求
- 删除成功后弹出成功提示,然后跳转到列表页面
Ajax
- 删除成功后弹出成功提示,然后跳转到列表页面
1.2 引入JSON类库
<!--spring-json依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
1.3 R 类
image-20191024120128217.png
package com.imcode.common.model;
import java.util.HashMap;
public class R extends HashMap<String, Object> {
public static R ok() {
R r = new R();
r.put("code", 0);
r.put("msg", "请求成功");
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("code", 0);
r.put("msg", msg);
return r;
}
public static R ok(String msg, Object data) {
R r = new R();
r.put("code", 0);
r.put("msg", msg);
r.put("data", data);
return r;
}
public static R error(String msg) {
R r = new R();
r.put("code", 1);
r.put("msg", msg);
return r;
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
@Override
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}
2. @ResponseBody 返回JSON数据
该注解用于将Controller
的方法返回的对象,通过适当的HttpMessageConverter
转换为指定格式后,写入到Response
对象的body
数据区
2.1 获取角色列表数据
model
image-20191024115612412.png
public class Role {
private Integer id;
private String roleName;
private String remark;//角色描述
private Date createTime;
private Date updateTime;
...
}
controller
image-20191024115451715.png
@Controller
@RequestMapping("/role")
public class RoleController {
/**
* 获取角色列表的数据
* @return
*/
@GetMapping("/data_list")
@ResponseBody
public R dataList(){
List<Role> list = new ArrayList<>();
for (int i=1;i<=10;i++){
Role role = new Role();
role.setId(i);
role.setRoleName("角色名称" + i);
role.setRemark("角色描述" + i);
role.setCreateTime(new Date());
role.setUpdateTime(new Date());
list.add(role);
}
R data = R.ok();
data.put("total",500);
data.put("rows",list);
return data;
}
}
响应数据
image-20191024124905712.png
日期返回的是时间戳,处理成我们需要的日期格式
@JsonFormat
该注解是jackson
类库提供的注解,使用在对象的属性上,在使用jackson
的api序列化和反序列java对象的时候,按pattern
属性定义的日期格式对日期进行格式化。
timezone
:设置时区,GMT+8表示东八区
image-20191024125105691.png
再次测试
image-20191024125225107.png
2.2 展示角色列表数据
controller
image-20191024125817738.png
jsp
<div class="x_panel">
<div class="row x_title">
<div class="col-md-6">
<h2>角色列表</h2>
</div>
<div class="col-md-6 pull-right">
<div class="pull-right">
<a href="${ctx}/role/add" class="btn btn-info btn-sm">新增</a>
</div>
</div>
</div>
<div class="x_content">
<table id="data-table"></table>
</div>
</div>
BootstrapTable 表格插件
<div class="x_content">
<table id="data-table"></table>
</div>
<script src="${ctx}/static/lib/jquery/jquery.js"></script>
<script src="${ctx}/static/lib/bootstrap/js/bootstrap.js"></script>
<script src="${ctx}/static/lib/layer/layer.js"></script>
<script src="${ctx}/static/lib/bootstrap-table/bootstrap-table.js"></script>
<script src="${ctx}/static/lib/bootstrap-table/bootstrap-table-zh-CN.js"></script>
<script>
// var list_url = '${ctx}/static/data/role_list.json';
var list_url = '${ctx}/role/data_list';
// 初始化表格数据
var dataTable = $('#data-table').bootstrapTable({
url: list_url, // 请求后台的URL
method: "get", // 请求方式
uniqueId: "id", // 每一行的唯一标识,一般为主键列
cache: false, // 设置为 false 禁用 AJAX 数据缓存, 默认为true
pagination: true, // 是否显示分页
sidePagination: "client", // 分页方式:client客户端分页,server服务端分页
pageSize: 10, // 每页的记录行数
queryParamsType: '',
queryParams: function (param) {
return {
pageNum: param.pageNumber,
pageSize: param.pageSize,
roleName: $("#roleName").val()
}
},
columns: [{
field: 'roleName',
title: '角色名称'
}, {
field: 'remark',
title: '角色描述'
}, {
field: 'createTime',
title: '创建时间'
}, {
field: 'updateTime',
title: '最后更新时间'
}, {
field: 'operate',
title: '操作',
formatter:
'<a href="javascript:;" class="update">修改</a> | ' +
'<a href="javascript:;" class="del">删除</a>'
,
events: {
'click .update': function (event, value, row) {
//window.location.href = 'role_update.html?id='+ row.roleId
},
'click .del': function (event, value, row, index) {
layer.confirm("确认删除?", {icon: 3, offset: '0px'}, function () {
$.ajax({
url: 'data/response.json',
type: 'get',
success: function (response) {
if (response.code == 0) {
layer.msg(response.msg, {icon: 1, time: 1000}, function () {
dataTable.bootstrapTable('refresh', {
url: list_url
});
});
} else {
layer.alert(response.msg);
}
}
})
})
}
}
}]
});
// 查询
$('#btn-search').click(function () {
dataTable.bootstrapTable('refresh', {
url: list_url
});
});
</script>
运行效果
image-20191024130315584.png
2.3 新增角色
controller
/**
* 跳转到新增角色页面
* @return
*/
@GetMapping("/add")
public String add(){
return "sys/role_add";
}
/**
* 新增角色
* @param role
* @return
*/
@PostMapping("/add")
@ResponseBody
public R add(Role role){
System.out.println(role);
return R.ok();
}
响应数据
image-20191024131415139.png
js
$('#data-form').parsley().on('form:submit', function () {
$.ajax({
//url: '${ctx}/static/data/response.json',
url: '${ctx}/role/add',
type: 'post',
data: $("#data-form").serialize(),
dataType: 'json',
success: function (response) {
if (response.code == 0) {
layer.msg(response.msg, {
icon: 1,
time: 2000,
offset: '0px'
}, function (index) {
window.location.href = '${ctx}/role/list';
});
} else {
layer.alert(response.msg, {icon: 5, offset: '0px'});
}
}
})
});
3. @RequestBody 接收JSON数据
ResponseBody java对象---> json字符串
RequestBody json字符串-->java对象
该注解用于读取Request
请求的body
部分数据,使用系统默认配置的HttpMessageConverter
进行解析,然后把相应的数据绑定到要返回的对象上
再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上
3.1 修改角色
controller
@GetMapping("/update/{id}")
public String update(@PathVariable Integer id, Model model) {
Role role = new Role();
role.setId(id);
role.setRoleName("系统管理员");
role.setRemark("描述信息");
model.addAttribute("role",role);
return "sys/role_update";
}
@PostMapping("/update")
@ResponseBody
// @RequestBody 将从客户端接收到的json字符串转换成java对象
public R update(@RequestBody Role role) {
System.out.println(role);
return R.ok();
}
postman测试
image-20191024150045001.png
js
function form2Json(formId) {
var arr = $(formId).serializeArray();
var jsonObj = {};
for (var index in arr) {
jsonObj[arr[index].name] = arr[index].value;
}
return JSON.stringify(jsonObj);
}
$('#data-form').parsley().on('form:submit', function () {
var arr = $("#data-form").serializeArray();
var jsonObj = {};
for (var index in arr) {
jsonObj[arr[index].name] = arr[index].value;
}
$.ajax({
url: '${ctx}/role/update',
type: 'post',
data: form2Json('#data-form'),
dataType: 'json',
contentType:"application/json;charset=utf-8",
success: function (response) {
if (response.code == 0) {
layer.msg(response.msg, {icon: 1, time: 1000, offset: '0px'}, function (index) {
window.location.href = 'role_list.html';
});
} else {
layer.alert(response.msg, {icon: 5, offset: '0px'});
}
}
})
});
4. 文件上传
4.1 环境搭建
-
在
pom.xml
引入common-file-upload
依赖<!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
-
在
springmvc-config.xml
配置文件解析器<!--文件上传解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 限制文件上传总大小,不设置默认没有限制,单位为字节 200*1024*1024即200M --> <property name="maxUploadSize" value="209715200" /> <!-- 设置每个上传文件的大小上限 1024*1024*2 2M --> <property name="maxUploadSizePerFile" value="2019152"/> <!-- 处理文件名中文乱码 --> <property name="defaultEncoding" value="UTF-8" /> <!-- resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 --> <property name="resolveLazily" value="true" /> </bean>
4.2 单文件上传
<form method="post" action="${ctx}/upload01" enctype="multipart/form-data" id="data-form">
<input type="file" name="uploadFile"><br>
<button>提交</button>
</form>
@PostMapping("/upload01")
@ResponseBody
public R upload(MultipartFile uploadFile) {
try {
System.out.println(uploadFile.getName());//表单name属性的值
System.out.println(uploadFile.getOriginalFilename());//文件名称
System.out.println(uploadFile.getSize());
//保存文件到磁盘
File file = new File("D:/" + uploadFile.getOriginalFilename());
uploadFile.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
return R.error(e.getMessage());
}
return R.ok("文件上传成功");
}
4.3 多文件上传
<form method="post" action="${ctx}/upload02" enctype="multipart/form-data" id="data-form" >
<input type="file" name="uploadFile"><br>
<input type="file" name="uploadFile"><br>
<input type="file" name="uploadFile"><br>
<input type="file" name="uploadFile"><br>
<button>提交</button>
</form>
@PostMapping("/upload02")
@ResponseBody
public R upload(@RequestParam("uploadFile") MultipartFile[] multipartFile) {
try {
for(MultipartFile uploadFile : multipartFile){
//保存文件到磁盘
File file = new File("D:/" + uploadFile.getOriginalFilename());
uploadFile.transferTo(file);
}
} catch (IOException e) {
e.printStackTrace();
return R.error(e.getMessage());
}
return R.ok("文件上传成功");
}
4.4 上传文件到服务器
- 思路:将图片上传到工程的发布目录下,工程发布目录下的资源可以通过http协议直接访问到
@Controller
@RequestMapping("/common/file")
public class FileController {
@PostMapping("/upload")
@ResponseBody
public R uplaod(@RequestParam("uploadFile") MultipartFile uploadFile, HttpSession session) {
try {
String fileName = uploadFile.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".") - 1);
String uuid = UUID.randomUUID().toString().toUpperCase().replace("-", "");
String uploadFileName = uuid + suffix;
String realPath = session.getServletContext().getRealPath("upload");
File file = new File(realPath + File.separator + uploadFileName);
uploadFile.transferTo(file);
return R.ok()
.put("url", "http://localhost:8080/admin/upload/" + uploadFileName)
.put("name",uploadFileName);
} catch (IOException e) {
e.printStackTrace();
return R.error(e.getMessage());
}
}
}
4.5 文件上传插件-dropzone
dropzone 文档地址
https://gitlab.com/meno/dropzone
参考资料:
https://www.jianshu.com/p/eaf870f7c88e 入门文章
https://www.cnblogs.com/webenh/p/6143237.html 官方文档翻译
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%--获取应用上下文的路径--%>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<title>i-admin 后台管理系统 - 文件上传</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="${ctx}/static/lib/bootstrap/css/bootstrap.css" rel="stylesheet">
<link href="${ctx}/static/lib/font-awesome/css/font-awesome.css" rel="stylesheet">
<link href="${ctx}/static/lib/dropzone/basic.css" rel="stylesheet">
<link href="${ctx}/static/lib/dropzone/dropzone.css" rel="stylesheet">
<link href="${ctx}/static/css/custom.css" rel="stylesheet">
</head>
<body class="content_col">
<div>
<div class="x_panel">
<div class="x_title">
<h2>ajax文件上传 - dropzone</h2>
<div class="clear"></div>
</div>
<div class="x_content">
<div class="dropzone" id="my-awesome-dropzone"></div>
</div>
</div>
</div>
<script src="${ctx}/static/lib/jquery/jquery.js"></script>
<script src="${ctx}/static/lib/bootstrap/js/bootstrap.js"></script>
<script src="${ctx}/static/lib/layer/layer.js"></script>
<script src="${ctx}/static/lib/dropzone/dropzone.js"></script>
<script src="${ctx}/static/lib/nprogress/nprogress.js"></script>
<script src="${ctx}/static/js/custom.js"></script>
<script>
$("#my-awesome-dropzone").dropzone({
url: "${ctx}/upload", // 服务器后台的路径
paramName: "uploadFile", // 设置表单名称
init: function () {
this.on("success", function (file, data) {
console.log(data);
});
}
});
</script>
</body>
</html>
5. 封装文件上传服务
5.1 application.properties
将上传文件有关的配置抽取到配置文件
image-20191028012601736.png
file.server=http://localhost:8080/admin/upload
file.location = /upload
5.2 FileService
image-20191028012831161.png
@Service
public class FileService {
@Value("${file.server}")
private String fileServer;
@Value("${file.location}")
private String fileLocation;
@Autowired(required = false)
HttpSession session;
/**
* 上传文件
*
* @param uploadFile
* @return
* @throws IOException
*/
public R upload(MultipartFile uploadFile) throws IOException {
String fileName = uploadFile.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".") - 1);
String uuid = UUID.randomUUID().toString().toUpperCase().replace("-", "");
fileName = uuid + suffix;
String parent = session.getServletContext().getRealPath(fileLocation);
File file = new File(parent, fileName);
if (!file.exists()) {
file.mkdirs();
}
uploadFile.transferTo(file);
return R.ok()
.put("url", fileServer + "/" + fileName)
.put("name", fileName);
}
}
5.3 FileController
image-20191028012950710.png
@Controller
@RequestMapping("/common/file")
public class FileController {
@Autowired
private FileService fileService;
/**
* 单文件上传
*
* @param uploadFile
* @return
*/
@PostMapping("/upload")
@ResponseBody
public R uplaod(@RequestParam("uploadFile") MultipartFile uploadFile) {
try {
return fileService.uplaod(uploadFile);
} catch (IOException e) {
e.printStackTrace();
return R.error(e.getMessage());
}
}
/**
* 多文件上传
*
* @param uploadFile
* @param session
* @return
*/
@PostMapping("/uploads")
@ResponseBody
public R uplaods(@RequestParam("uploadFile") MultipartFile[] uploadFile) {
List<Map<String, Object>> data = new ArrayList<>();
for (MultipartFile f : uploadFile) {
try {
data.add(fileService.uplaod(f));
} catch (IOException e) {
e.printStackTrace();
data.add(R.error(e.getMessage()));
}
}
return R.ok().put("data", data);
}
}
5.4 获取Request和Session对象
在web.xml
添加监听器
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
在普通类中获取
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
在Bean类中获取
@Controller
public class XxxController {
@Autowired
public HttpSession session;
@Autowired
public HttpServletRequest request;
...
}
@Service
public class XXXService {
@Autowired
public HttpSession session;
@Autowired
public HttpServletRequest request;
...
}