栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

二、Spring MVC 进阶

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

二、Spring MVC 进阶

一、Ajax异步交互传递json格式的数据

Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入jackson的包;同时使用 这个注解实现其他数据和json数据之间的转换。

        
            com.fasterxml.jackson.core
            jackson-databind
            2.9.8
        
        
            com.fasterxml.jackson.core
            jackson-core
            2.9.8
        
        
            com.fasterxml.jackson.core
            jackson-annotations
            2.9.0
        

       
    
    

1.@RequestBody & @ResponseBody

@RequestBody: 该注解用于Controller的方法的形参声明,当使用ajax提交并指定contentType为json形式时,通过HttpMessageConverter接口将json数据转换为对应的POJO对象。
@ResponseBody: 该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
ajax.jsp

<%--
  Created by IntelliJ IDEA.
  User: ASUS
  Date: 2021/10/22
  Time: 10:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    ajax异步请求传输json数据格式的字符串


<%--在网络传输中数据的格式有json、xml格式的。json比较流行--%>
<%--1.导入jQuery包,利用api发送ajax请求--%>


<%--2.按钮dom对象--%>



<%--3.编写js代码,发送ajax异步请求--%>



Controller

@Controller // 将创建的UserController对象存储到Spring MVC创建的ioc容器中(子容器)
@RequestMapping("/user")    // 一级访问目录
public class UserController {

    @RequestMapping(value = "/ajaxRequestList",method = RequestMethod.POST)
    @ResponseBody
    public List ajaxRequestList(@RequestBody List list) {
        System.out.println(list);
        return list;
    }

    
    @RequestMapping("/ajaxRequestPojo")
    @ResponseBody
    public User ajaxRequestPojo(@RequestBody User user) {
        System.out.println(user);
        return user;
    }
}

二、Restful风格 1.什么是RESTful?

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用 “url+请求方式” 表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:

  • GET:读取(Read)
  • POST:新建(Create)
  • PUT:更新(Update)
  • DELETE:删除(Delete)
客户端请求原来风格URL地址RESTful风格URL地址
查询所有/user/findAllGET /user
根据id查询/user/findByIdGET /user/1
新增/user/savePOST /user
修改/user/updatePUT /user/1
删除/user/deleteDELETE /user/1

2.代码实现
  • @PathVariable 用来接收RESTful风格请求地址中占位符的值
  • @RestController RESTful风格多用于前后端分离项目开发,前端通ajax与服务器进行异步交互,我们处理器通常返回的是json数据所以使用@RestController来替代@Controller和@ResponseBody两个注解。
  • @GetMapping/@PostMapping/@PutMapping/@DeleteMapping 这四个注解替代了@RequestMapping注解。@GetMapping("/user/{id}")就相当于@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
import cn.xuguowen.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


// @Controller
@RestController // 组合注解:相当于@Controller + @ResponseBody 两个注解的功能
@RequestMapping("/restful")     // 一级访问路径
public class RestfulController {
    
    // {id}是Restful中的占位符。请求路径和请求方式组合起来就是根据id查询用户的功能
    // @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    @GetMapping("/user/{id}")
    // @ResponseBody
    public String findById(@PathVariable  Integer id) {
        // 实际开发中,要调用业务层的的查询方法,将获取到的id值传递
        // 那么问题来了:如何获取到参数id的值并且将赋值给形参中的id呢?
        // 解决问题:使用注解@PathVariable将参数id值赋值给形参id

        // 问题二:这样写返回值,框架会认为是字符串逻辑视图名称,那么视图解析器会拼接前缀和后缀,这样的话就会出现404的错误
        // 如何解决这个问题呢?使用@ResponseBody注解,就不会经过视图解析器了,就是将字符串内容写在了页面上
        return "findById:" + id;
    }

    
    // 原始请求url:localhost:8080/项目名称/restful/user
    // Restful请求方式:localhost:8080/项目名称/restful/user + 请求方式
    // @RequestMapping(value = "/user",method = RequestMethod.GET)
    @GetMapping("/user")
    // @ResponseBody
    public String findAll() {
        return "findAll";
    }

    
    // @RequestMapping(value = "/user",method = RequestMethod.POST)
    @PostMapping("/user")
    // @ResponseBody
    public String insert(User user) {
        System.out.println(user);
        return "insert";
    }

    // 修改(put)和删除(delete)用户信息的测试可以在postman软件中测试

    
    // @RequestMapping(value = "/user/1",method = RequestMethod.PUT)
    @PutMapping("/user/{id}")
    // @ResponseBody
    public String update(@PathVariable Integer id) {
        System.out.println("用户的id是:" + id);
        return "update";
    }

    
    // @RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
    @DeleteMapping("/user/{id}")
    // @ResponseBody
    public String delete(@PathVariable Integer id) {
        System.out.println("用户的id值为 " + id);
        return "delete";
    }
}


三、文件上传 1.文件上传的三要素
  • 表单项 type=“file”
  • 表单的提交方式 Method=“POST”
  • 表单的enctype属性是多部件表单形式 enctype=“multipart/form-data”
2.文件上传原理
  • 当form表单的enctype取值为application/x-www-form-urlencoded时,form表单的正文内容格式是:name=value&name=value键值对。在这种情况下,使用request.getParameter()是可以根据表单项name的属性值获取到表单项的value值
  • 当form表单的enctype取值为mutilpart/form-data时,请求正文内容就变成多部件表单形式
3.单文件上传

导入fileupload和io依赖坐标

 
        
            commons-fileupload
            commons-fileupload
            1.3.3
        
        
            commons-io
            commons-io
            2.6
        

在Spring mvc的核心配置文件中配置文件上传解析器

 
    
        
        
        
        
        
    

fileUpload.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    测试文件上传


<%--
    1.请求方式为post
    2.表单为多部件上传表单enctype="multipart/form-data"
    3.必须存在type="file" 的表单项
--%>
名称:
上传文件:

FileUploadController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;



@Controller
public class FileUploadController {
    
    @RequestMapping("/fileUpload")
    public String fileUpload(String username, MultipartFile filePic) {
        System.out.println("名称:" + username);
        // System.out.println(filePic);
        try {
            // 获取文件的原始名称来充当上传后的文件名称
            String originalFilename = filePic.getOriginalFilename();
            // 1.实现文件的上传
            filePic.transferTo(new File("D:/xxx/" + originalFilename));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 文件上传成功 跳转到success.jsp页面上,视图解析器会为逻辑视图拼接上前缀和后缀的
        return "success";
    }
}


4.多文件上传

fileUpload.jsp

<%--多文件上传--%>
名称:
上传文件:

FilesUploadController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;


@Controller
public class FilesUploadController {
    
    @RequestMapping("/filesUpload")
    public String filesUplodad(String username, MultipartFile[] filePic) {
        System.out.println(username);

        // 遍历数组。获取到每个文件对象,单独操作
        for (MultipartFile multipartFile : filePic) {
            try {
                // 获取原始的文件名称
                String originalFilename = multipartFile.getOriginalFilename();
                // 将文件上传到本地磁盘中
                multipartFile.transferTo(new File("D:/xxx/" + originalFilename));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }
}


四、异常处理 1.在Java中,对于异常的处理一般有两种方式:
  • 一种是当前方法捕获处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合。
  • 另一种是自己不处理,而是抛给调用者处理(throws),调用者再抛给它的调用者,也就是一直向上抛。在这种方法的基础上,衍生出了SpringMVC的异常处理机制。
  • 系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

2.自定义异常处理器 ①:创建异常处理器类实现HandlerExceptionResolver接口
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class GlobalExceptionResolver implements HandlerExceptionResolver {
    
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error",e.getMessage());
        // 逻辑视图名称:会经过视图解析器进行前缀和后缀的拼接
        modelAndView.setViewName("error");
        return modelAndView;
    }
}
②:在mvc的核心配置文件中配置异常处理器(生成实例化对象)
    
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
}
③:编写异常页面 error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    错误页面


这是一个全局异常页面!

${error}
④:测试异常跳转
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class TestExceptionController {
    
    @RequestMapping("/testException")
    public String testException() {
        int i = 1 / 0;
        // 逻辑视图:拼接前缀和后缀
        return "success";
    }
}

3.Web异常处理机制

web.xml

    
        500
        /500.jsp
    
    
    
        404
        /404.jsp
    

500.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


服务器端错误,请您稍后重试!



404.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


宝,您请求的资源不存在!




五、拦截器 1.拦截器(interceptor)的作用

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器中的方法进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

2.拦截器和过滤器的区别
区别过滤器拦截器
使用范围是Servlet规范中的一部分,任何 Java Web工程都可以使用是Spring MVC框架自己的,只有使用了Spring MVC框架的工程才可以使用
拦截范围在url-pattern中配置了 public class MyInterceptor1 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle1执行了!"); // 放行 return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle1执行了!"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion1执行了!"); } } ②:在mvc核心配置文件中配置拦截器链
    
        
        
            
             

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


<%--el表达式获取request域中存储的数据--%>

Success...${username}

<% System.out.println("视图跳转渲染完成,整个流程执行完毕了!"); %>

4.拦截器链

开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链。开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序(postHandle()和afterCompletion()两个方法的执行顺序和拦截器配置的顺序相反)。
自定义拦截器2

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MyInterceptor2 implements HandlerInterceptor {
    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2执行了!");
        // 放行
        return true;
    }

    
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2执行了!");
    }

    
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2执行了!");
    }
}

配置拦截器链

    
        
        
            
             
            
            
        
        
            
            
        
    
5.拦截器中方法的介绍
方法名说明
preHandle()该方法将在请求处理之前进行调用,该方法的返回值布尔类型的,当它返回false时,表示请求结束,后续的interceptor和controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor的preHandle(),如果没有则调用controller中的方法
postHandle()该方法是在当前请求进行处理之后被调用,前提是preHandle()方法的返回值为true时才能被调用,且它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作
afterCompletion()该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,前提是preHandle()方法的返回值为true时才能被调用
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号