SpringMVC(3)——json,异常处理,文件上传,RestFul,拦截器

1 SpringMVC对json支持

  1. 导入依赖:jackson-databind
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>

  1. 控制层 方法上添加注解@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);
    }
}
  1. 编写数据传输层dto:JsonResult.java,统一返回格式
public class JsonResult<T> {
    private Integer code;// 消息码
    private String msg; // 信息
    private T data; // 附带数据
    // ...三个构造函数,getter/setter方法
}
  1. 改变控制层的方法
    注意:注解 @RestController 代替 @Controller,不用每个方法上都写 @ResponseBody 返回 json 格式。

  2. 页面,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="">&laquo;</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="">&raquo;</a></li>'));
                }
            }
        })
    }
</script>

2 SpringMVC异常处理器

在请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
在这里插入图片描述
处理思路:
系统中异常:预期异常,运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试,通过手段减少运行时异常的发生,系统的dao、service、controller 出现通过 throws Exception向上抛出,最后由springMVC前端控制器交由异常处理器进行异常处理。

2.1 demo

  1. 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());
    }
}
  1. 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 步骤

  1. 导入依赖
<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
  1. 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
  1. 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()方法
}
  1. 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>
  1. 控制器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();
        }
    }
}
  1. 测试

4 对RestFul的支持

架构风格、设计风格,提供一组设计原则和约束条件。主要用于客户端和服务器组件,使软件设计更简洁、有层次,更有易于实现缓存等机制。
在这里插入图片描述
demo:
在这里插入图片描述
在这里插入图片描述
将动态的 id 用{}括起来;
在方法的形参前,使用@PathVariable 注解,将 url 上的参数封装到形参上;
如果是多参数,url 应为: /user/{name}/{id},多个参数使用/隔开;
对于多参数的 url,在方法的形参上使用多个参数接收,每个参数前都要添加@PathVariable 注解。

结果用postman测试

5 拦截器

类似于过滤器Filter,用于对处理器进行预处理和后处理,拦截方法。
解耦作用,与业务无关。

  1. 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---页面渲染完成");
    }
}
  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才调用

发布了79 篇原创文章 · 获赞 7 · 访问量 1836

猜你喜欢

转载自blog.csdn.net/weixin_45044097/article/details/103143650