1 SpringMVC对json支持
- 导入依赖:jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
- 控制层 方法上添加注解@ResponseBody:将 java 对象解析为 json 格式得到字符串返回。
public class DeptJsonController {
@Autowired
private DeptService ds;
/**
* 数据列表页面
*/
@GetMapping("/dept/list_json/page")
public String listPage(){
return "dept/list-json";
}
/**
* 获取数据的方法
*/
@RequestMapping(value = "/dept/list_json",method = RequestMethod.POST)
@ResponseBody
public JsonResult<PageInfo> getList(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "2") Integer pageSize){
// 调用service获取部门数据
PageInfo<Dept> pageInfo = ds.list(page, pageSize);
return new JsonResult(200,"success!",pageInfo);
}
}
- 编写数据传输层dto:JsonResult.java,统一返回格式
public class JsonResult<T> {
private Integer code;// 消息码
private String msg; // 信息
private T data; // 附带数据
// ...三个构造函数,getter/setter方法
}
-
改变控制层的方法
注意:注解 @RestController 代替 @Controller,不用每个方法上都写 @ResponseBody 返回 json 格式。 -
页面,json代码
<script type="text/javascript">
/**
* 删除的方法
* @param id
*/
function del(id) {
if(confirm("确定删除吗?")){
window.location.href="${pageContext.request.contextPath}/dept/delete?id="+id;
}
}
/**
* 通过ajax去获取对应的列表相关数据
*/
$(function() {
// 获取第一页的数据
getData(1);
});
/**
* 获取数据的方法
* @Param page : 当前的页码
*/
function getData(page) {
$.ajax({
url:"${pageContext.request.contextPath}/dept/list-json",
type:"post",
data:{page:page},
dataType:"json",
success:function(data) {
console.log(data);
if(data.code == 200) {
// 1. 数据渲染到表格
// 清空数据
$("#t_data").empty();
$(data.data.list).each(function() {
// 每循环一次 创建一次
var tr=$('<tr>\n' +
' <td>'+this.id+'</td>\n' +
' <td>'+this.deptName+'</td>\n' +
' <td>'+this.deptDesc+'</td>\n' +
' <td>\n' +
' <a href="" type="button" class="btn btn-primary">编辑</a>\n' +
' <a href="" type="button" class="btn btn-primary">删除</a>\n' +
' </td>\n' +
' </tr>')
// 把创建好的行 追加到t_data
$("#t_data").append(tr);
});
// 2. 处理分页
// 先清空所有
$(".pagination").empty();
// 先追加第一页
$(".pagination").append($('<li class=""><a href="">«</a></li>'));
$(data.data.navigatepageNums).each(function() {
var li = $('<li class="'+(data.data.pageNum==this ? 'active' : '')+'">\n' +
' <a href="javascript:getData('+this+')">'+this+'</a>\n' +
' </li>');
//li.insertBefore("#nextPage");
$(".pagination").append(li);
})
// 追加最后一页
$(".pagination").append($('<li class=""><a href="">»</a></li>'));
}
}
})
}
</script>
2 SpringMVC异常处理器
在请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
处理思路:
系统中异常:预期异常,运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试,通过手段减少运行时异常的发生,系统的dao、service、controller 出现通过 throws Exception向上抛出,最后由springMVC前端控制器交由异常处理器进行异常处理。
2.1 demo
- MyException.java
public class MyException extends Exception {
private Integer code;
private String msg;
// 构造器,getter/setter方法
}
ServiceException.java与上面的一样
MyExceptionHandler.java
// 异常处理器: 捕获所有的异常
@RestControllerAdvice
public class MyExceptionHandler {
// 捕获对应的异常信息
@ExceptionHandler(MyException.class)
public JsonResult MyExceptionHand(MyException e){
// 进行一些异常的信息封装
// 记录日志
// 返回给前端的错误信息
return new JsonResult(e.getCode(),e.getMsg());
}
// 处理service的异常信息
@ExceptionHandler(ServiceException.class)
public JsonResult ServiceExceptionHand(ServiceException e){
// 进行一些异常的信息封装
// 记录服务处的错误日志
// 返回给前端的错误信息
return new JsonResult(e.getCode(),e.getMsg());
}
}
- controller层:ExceptionController.java
@RestController
public class ExceptionController {
@GetMapping("/exception/index")
public JsonResult index(Integer id) throws MyException {
if(id <= 0){
throw new MyException(3001,"id错误!");
}
return new JsonResult(200,"成功",id);
}
}
3 文件上传
3.1 配置文件服务器
现在项目是maven插件运行的,所以配置文件服务器需要配置一个Tomcat服务器,端口号不能和8080冲突。
指定文件服务器的根路径:
3.2 步骤
- 导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- upload.jsp 页面
<div class="container">
<h1>文件上传</h1>
<form role="form" method="post" action="${pageContext.request.contextPath}/upload/do1" enctype="multipart/form-data">
<div class="form-group">
<label for="name">名称</label>
<input type="text" class="form-control" id="name" placeholder="请输入名称">
</div>
<div class="form-group">
<label for="inputfile">头像</label>
<input type="file" name="header" id="inputfile">
</div>
<button type="submit" class="btn btn-default">提交</button>
</form>
</div>
重点:enctype=“multipart/form-data”
name="header"和后面controller层的文件名是一样的,不然注入不进去。
3. 创建sys.properties,解决硬编码问题。
# 文件上传的根路径
sys.basePath=E:/upload/
# 允许上传的后缀
sys.suffixs=.png|.jpg|.gif
- config包,SystemConfig.java
@Configuration
@PropertySource("classpath:config/sys.properties")
public class SystemConfig {
@Value("${sys.basePath}")
private String basePath;
@Value("${sys.suffixs}")
private String suffixs;
// 构造器,getter,setter,重写toString()方法
}
- spring-web.xml添加扫描config包,配置文件解析器(前端控制器同理)
<!-- 开启注解扫描,扫描controller包,有多个用逗号隔开-->
<context:component-scan base-package="com.java201.controller,com.java201.exception,com.java201.config"/>
<bean name="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--上传的大小-->
<property name="maxUploadSize" value="50000"/>
<!--设置编码-->
<property name="defaultEncoding" value="utf-8"/>
</bean>
- 控制器UploadController.java
@SuppressWarnings("all")
@Controller
public class UploadController {
@Autowired
private SystemConfig sysc;
// 上传的页面
@GetMapping("/upload/page")
public String page(){
return "upload/upload";
}
// 文件上传的方法
@PostMapping("/upload/do")
@ResponseBody
public JsonResult upload(MultipartFile header) throws IOException {
// 判断是否有文件上传过来
if (!header.isEmpty()) {
// 获取文件的名字
String filename = header.getOriginalFilename();
// 获取文件保存的路径
String path = "D:/upload/";
// 准备文件抽象的File对象
File file = new File(path + filename);
// 上传
header.transferTo(file);
return new JsonResult(200,"上传成功",filename);
}
return new JsonResult(400,"上传失败!");
}
@PostMapping("/upload/do1")
@ResponseBody
public JsonResult upload1(MultipartFile header) throws IOException {
// 判断是否有文件上传过来
if (!header.isEmpty()) {
// 获取文件的名字
String filename = header.getOriginalFilename();
// 解析文件的后缀
String suffix = FileUtil.getSuffix(filename);
if(suffix==null){
return new JsonResult(4003,"文件名不符合规范!");
}
// 判断后缀是否符合需求
String suffixs = sysc.getSuffixs();
if(!suffixs.contains(suffix)){
return new JsonResult(4004,"文件类型不符合要求!");
}
// 获取唯一的文件名
String uploadFileName = FileUtil.getUniqueFileName();
// 获取文件保存的路径
String datePath = FileUtil.getDatePath();
// 获取文件保存的路径
String basePath = sysc.getBasePath();
// 先创建上传的路径
FileUtil.createDir(basePath+datePath);
// 准备文件抽象的File对象
File file = new File(basePath + datePath + uploadFileName + suffix);
// 上传
header.transferTo(file);
return new JsonResult(200,"上传成功",datePath + uploadFileName + suffix);
}
return new JsonResult(400,"上传失败!");
}
}
处理文件相关的一些操作 帮助类FileUtil.java:
public class FileUtil {
// 获取文件名的后缀
public static String getSuffix(String fileName){
// 检测文件名
if (fileName == null || fileName.isEmpty()) {
return null;
}
// 解析后缀
// aa.jpg aa.bb.jpg bb.cc.aa.png
if (fileName.lastIndexOf(".") == -1) {
return null;
}
// 截取字符串
String suffix = fileName.substring(fileName.lastIndexOf("."));
return suffix;
}
// 获取唯一的文件名
public static String getUniqueFileName(){
return UUID.randomUUID().toString().replaceAll("-", "");
}
// 获取日期的路径
public static String getDatePath(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
return sdf.format(new Date());
}
// 创建文件夹
public static void createDir(String path){
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
}
}
- 测试
4 对RestFul的支持
架构风格、设计风格,提供一组设计原则和约束条件。主要用于客户端和服务器组件,使软件设计更简洁、有层次,更有易于实现缓存等机制。
demo:
将动态的 id 用{}括起来;
在方法的形参前,使用@PathVariable 注解,将 url 上的参数封装到形参上;
如果是多参数,url 应为: /user/{name}/{id},多个参数使用/隔开;
对于多参数的 url,在方法的形参上使用多个参数接收,每个参数前都要添加@PathVariable 注解。
结果用postman测试
5 拦截器
类似于过滤器Filter,用于对处理器进行预处理和后处理,拦截方法。
解耦作用,与业务无关。
- Myinterceptor.java 自定义 实现接口HandlerInterceptor,返回值决定是否放行
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器1---方法执行之前");
// 返回true放行,返回false 不放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器1---方法执行之后");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器1---页面渲染完成");
}
}
- 注册拦截器spring-web.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 指定不拦截的方法-->
<mvc:exclude-mapping path="/dept/deptList"/>
<bean class="com.java201.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
path 的讲解:
path=”/” 什么都不拦截
path=”/ * ”能拦截:/dept.action,不能拦截/dept/list.action
path=”/ ** ”能拦截所有
path=”/dept/*” 能拦截/dept/下面的所有
preHandler 按拦截器定义顺序调用
postHandler 按拦截器定义逆序调用
afterCompletion 按拦截器定义逆序调用
postHandler 在拦截器链内所有拦截器返回成功调用
afterCompletion 只有preHandler 返回true才调用