java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringMVC请求、响应和拦截器

SpringMVC请求、响应和拦截器的使用实例详解

作者:青城小虫

拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的,这篇文章给大家介绍SpringMVC请求、响应和拦截器的使用,感兴趣的朋友一起看看吧

SpringMVC请求

RequestMapping注解

RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
RequestMapping注解可以作用在方法和类上

1. 作用在类上:第一级的访问目录
2. 作用在方法上:第二级的访问目录
3. 细节:路径可以不编写 / 表示应用的根目录开始

(1).RequestMapping的属性

1. path 指定请求路径的url
2. value value属性和path属性是一样的
3. mthod 指定该方法的请求方式

@Controller
@RequestMapping(path = "/role") // 一级请求路径
public class RoleController {
    /**
     * /role/save
     * method="当前方法允许请求方式能访问"
     * params="请求路径上传参数"
     * @return
     */
   @RequestMapping(path = "/save",method = {RequestMethod.GET})
    public String save(){
        System.out.println("保存角色...");
        return "suc";
    }
    @RequestMapping(value = "/delete")
    public String delete(){
        System.out.println("删除角色...");
        return "suc";
    }
}

(2).RequestMapping的请求参数绑定

1. 绑定机制

2. 支持的数据类型

基本数据类型和字符串类型

实体类型(JavaBean)

给集合属性数据封装
JSP页面编写方式:list[0].属性

jsp代码

<html>
<head>
    <meta charset="utf-8">
    <title>入门程序</title>
</head>
<body>
<h3>入门</h3><a href="/SpringMVC/hello" rel="external nofollow"  >入门程序</a>
    <h1>请求参数绑定入门程序</h1>
    <form action="/SpringMVC/user/save" method="get">
        <input type="text" name="username"/><br/>
        <input type="text" name="age"/><br/>
        <input type="submit"/>
    </form>
    <h1>请求参数绑定入门程序(封装到实体类)</h1>
    <form action="/user/save1" method="post">
        <input type="text" name="username"/><br/>
        <input type="text" name="age"/><br/>
        <input type="submit"/>
    </form>
    <h1>请求参数绑定入门程序(封装到实体类)</h1>
    <form action="/user/save2" method="post">
        <input type="text" name="username"/><br/>
        <input type="text" name="age"/><br/>
        <input type="text" name="account.money"/><br/>
        <input type="submit"/>
    </form>
    <h1>请求参数绑定入门程序(存在list集合)</h1>
    <form action="/user/save3" method="post">
        <input type="text" name="username"/><br/>
        <input type="text" name="age"/><br/>
        <input type="text" name="account.money"/><br/>
        <input type="text" name="accounts[0].money"/><br/>
        <input type="text" name="accounts[1].money"/><br/>
        <input type="submit"/>
    </form>
</body>
</html>

JavaBean代码

public class Account {
    private Double money;
    public Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account{" +
                "money=" + money +
                '}';
    }
}
public class User {
    private String username;
    private Integer age;
    private Account account;
    private List<Account> accounts;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Account getAccount() {
        return account;
    }
    public void setAccount(Account account) {
        this.account = account;
    }
    public List<Account> getAccounts() {
        return accounts;
    }
    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", account=" + account +
                ", accounts=" + accounts +
                '}';
    }
}

controller代码

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save")
    public String save(String username,Integer age){
        System.out.println(username);
        System.out.println(age);
        return "suc";
    }
    @RequestMapping("/save1")
    public String save1(User user){
        System.out.println(user.toString());
        return "suc";
    }
    @RequestMapping("/save2")
    public String save2(User user){
        System.out.println(user);
        return "suc";
    }
    @RequestMapping("/save3")
    public String save3(User user){
        System.out.println(user);
        return "suc";
    }
}

在控制器中使用原生的ServletAPI对象
只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

@RequestMapping(value = "/save6.do",method = {RequestMethod.POST})
public String save6(HttpServletRequest request, HttpServletResponse response){
    // 获取到HttpSession对象
    System.out.println(request.getParameter("username"));
    HttpSession session = request.getSession();
    System.out.println(session);
    System.out.println(response);
    return "suc";
}

SpringMVC响应

第一章:数据处理及跳转

1. 结果跳转方式

①.ModelAndView

设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面

<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
    <property name="prefix" value="/html/" />
    <property name="suffix" value=".html" />
    <property name="templateMode" value="HTML5"/>
</bean>

对应的controller类

/**
 * 返回ModelAndView对象的方式
 * @return
 */
@RequestMapping("/save3")
public ModelAndView save3(){
    System.out.println("执行了...");
    // 创建mv对象
    ModelAndView mv = new ModelAndView();
    // 把一些数据,存储到mv对象中
    mv.addObject("msg","用户名或者密码已经存在");
    // 设置逻辑视图的名称
    mv.setViewName("suc");
    return mv;
}

在这里插入图片描述

②.ServletAPI

通过设置ServletAPI , 不需要视图解析器 .

1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发

@Controller
@RequestMapping(path = "/role") // 一级请求路径
public class RoleController {
    @RequestMapping("/t1")
    public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.getWriter().println("Hello,Spring BY servlet API");
    }
    @RequestMapping("/t2")
    public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.sendRedirect("/SpringMVCDemo/html/suc.html");
    }
    @RequestMapping("/t3")
    public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
        //转发
        req.setAttribute("msg","hello");
        req.getRequestDispatcher("/html/suc.html").forward(req,rsp);
    }
}

③.SpringMVC

通过SpringMVC来实现转发和重定向 - 无需视图解析器;
测试前,需要将视图解析器注释掉

@Controller
@RequestMapping(path = "/role") // 一级请求路径
public class RoleController {
    @RequestMapping("/t1")
    public String test1(){
        //转发
        return "/html/suc.html";
    }
    @RequestMapping("/t2")
    public String test2(){
        //转发二
        return "forward:/html/suc.html";
    }
    @RequestMapping("/t3")
    public String test3(){
        //重定向
        return "redirect:/html/suc.html";
    }
}

2.ResponseBody响应json数据

json和JavaBean对象互相转换的过程中,需要使用jackson的jar包

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.9.0</version>
</dependency>

DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
标签配置不过滤

<!--设置静态资源不过滤-->
<mvc:resources mapping="/css/**" location="/css/"/> <!--样式-->
<mvc:resources mapping="/images/**" location="/images/"/> <!--图片-->
<mvc:resources mapping="/js/**" location="/js/"/> <!--javascript-->

html代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script>
        // 页面加载
        $(function(){
            // 单击事件
            $("#btn").click(function(){
            // 发送ajax的请求
                $.ajax({
                    type: "post",
                    url: "/SpringMVCDemo/user/save6",
                    data:{username:"haha",age:"20"},
                    success:function(d){
                        // 编写很多代码
                        alert(d.username+" ‐ "+d.age);
                    }
                });
            });
        });
    </script>
</head>
<body>
<h3>异步的数据交互</h3>
<input type="button" value="ajax交互" id="btn">
</body>
</html>

controller

/**
 * 异步的数据交互
 * 重定向
 * @return
 */
@RequestMapping("/save6")
public @ResponseBody User save6(User user){
    System.out.println(user);
    // 模拟,调用业务层代码
    user.setUsername("hello");
    user.setAge(100);
    // 把user对象转换成json,字符串,再响应。使用@ResposeBody注解 response.getWriter().print()
    return user;
}

在springMVC当中如果要实现页面跳转就不要使用ajax,如果要json数据的返回就用ajax

第二章:SpringMVC实现文件上传

导入文件上传的jar包

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

在Springmvc.xml配置文件上传解析器

<!--配置文件上传的解析器组件。id的名称是固定,不能乱写-->
 <bean id="multipartResolver"
       class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
 <!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
 <property name="maxUploadSize" value="8388608" />
 </bean>

编写文件上传的html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>文件上传</h3>
<form id="addForm"  action="/SpringMvc/file/upload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="file" width="120px">
    <input type="submit" value="上传">
</form>
<div id="upMenu" class="white_content">
    <form id="downForm"   lay-filter="updata" action="/SpringMvc/file/down" method="get">
        <input type="text" id="filename" name="filename">
        <input type="submit" value="下载">
    </form>
    <input type="button" value="完成"/>
</div>
</body>
</html>

controller层

@Controller
@RequestMapping("/file")
public class FileController {
    /**
     * 文件上传功能
     * @param file
     * @return
     * @throws IOException
     */
    @RequestMapping(value="/upload",method= RequestMethod.POST)
    @ResponseBody
    public  String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
        // uploads文件夹位置
        String rootPath = request.getSession().getServletContext().getRealPath("WEB-INF/upload");
        // 原始名称
        String originalFileName = file.getOriginalFilename();
        // 新文件
        File newFile = new File(rootPath + File.separator  + File.separator + originalFileName);
        // 判断目标文件所在目录是否存在
        if( !newFile.getParentFile().exists()) {
            // 如果目标文件所在的目录不存在,则创建父目录
            newFile.getParentFile().mkdirs();
        }
        System.out.println(newFile);
        // 将内存中的数据写入磁盘
        file.transferTo(newFile);
        return  "{\"data\":\"success\"}";
    }
    /**
     * 文件下载功能
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/down")
    public void down(HttpServletRequest request, HttpServletResponse response) throws Exception{
        String filename = request.getParameter("filename");
        System.out.println(filename);
        //模拟文件,myfile.txt为需要下载的文件
        String fileName = request.getSession().getServletContext().getRealPath("WEB-INF/upload")+"/"+filename;
        //获取输入流
        InputStream bis = new BufferedInputStream(new FileInputStream(new File(fileName)));
        //假如以中文名下载的话
       // String filename = "下载文件.txt";
        //转码,免得文件名中文乱码
        filename = URLEncoder.encode(filename,"UTF-8");
        //设置文件下载头
        response.addHeader("Content-Disposition", "attachment;filename=" + filename);
        //1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
        response.setContentType("multipart/form-data");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        int len = 0;
        while((len = bis.read()) != -1){
            out.write(len);
            out.flush();
        }
        out.close();
    }
}

第三章:SpringMVC的异常处理

1. 异常处理思路

Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进行异常的处理。

2. SpringMVC的异常处理

①:使用自己处理异常
controller代码

/**
 * 自己处理异常
 * @return
 */
@RequestMapping("/findAll")
public String findAll(Model model){
    try {
        System.out.println("执行了...");
        // 模拟异常
        int a = 10/0;
    }catch (Exception e){
        model.addAttribute("errorMsg","系统正在维护,请联系管理员");
        return "404";
    }
    return "suc";
}

404页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>错误提示页面</title>
</head>
<body>
<h1>404  <b th:text="${errorMsg}"></b></h1>
</body>
</html>

②:使用处理器处理异常
controller代码

/**
 * 使用异常处理器方式
 * @return
 */
@RequestMapping("/findAll2")
public String findAll2(){
    System.out.println("执行了...");
    //模拟异常
    int a = 10 / 0;
    return "suc";
}

自定义异常类

public class SysException extends Exception{
    // 提示消息
    private String message;
    public SysException(String message){
        this.message = message;
    }
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    @Override
    public String toString() {
        return "SysException{" +
                "message='" + message + '\'' +
                '}';
    }
}

配置异常处理器

<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="com.qcby.conf.SysExceptionResolver" />

SpringMVC拦截器

1.什么是拦截器

SpringMVC提供了Intercepter拦截器机制,类似于Servlet当中的Filter过滤器,用于拦截用户的请求并作出相应的处理,比如通过拦截器来进行用户权限验证或者用来判断用户是否登录。
SpringMVC拦截器是可插拔式的设计,需要某一功能拦截器,就需要在配置文件中应用拦截器即可;如果不需要这个功能拦截器,只需要在配置文件中取消该拦截器即可。

2.拦截器和过滤器有哪些区别

1.过滤器依赖于servlet,而拦截器技术属于SpringMVC
2.过滤器可对所有请求起作用,拦截器只对访问controller层的请求起作用。
3.过滤器会比拦截器先执行。拦截器(Interceptor)是在Servlet和Controller控制器之间执行;而过滤器(Filter)是在请求进入Tomcat容器之后 但是在请求进入Servlet之前执行。

在这里插入图片描述

3.拦截器方法

想要自定义拦截器,需要实现HandlerInterceptor接口。

我们可以看到 HandlerInterceptor接口有三个方法,分别是preHandle、postHandle、afterCompletion,关于这三个方法

4.单个拦截器的执行流程

程序首先会执行拦截器类中的preHandle()方法,如果该方法的返回值true,则程序继续向下执行处理器当中的方法,否则不在向下执行;业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向前端返回响应;在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。

在这里插入图片描述

5.使用拦截器实现用户登录权限验证

在这里插入图片描述

Controller层的设计

@Controller
public class LoginController {
    /**
     * 跳转登录页
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String loginPage(){
        System.out.println("跳转到login.html页面当中");
        return "login";
    }
    /**
     * 用户登录,成功到主页,失败回到登录页
     * @param user
     * @param model
     * @param session
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(User user, Model model, HttpSession session){
        if(user.getUsername() !=null && user.getUsername().equals("admin")
                && user.getPassword() !=null && user.getPassword().equals("123456")){
            System.out.println("用户登录功能实现");
            //将用户添加到session保存
            session.setAttribute("user",user);
            return "/suc";
        }
        model.addAttribute("msg","账户或密码错误,请重新登录");
        return "login";
    }
    /**
     * 跳转到主页
     * @return
     */
    @RequestMapping("/index")
    public String indexPage(){
        System.out.println("跳转到主页");
        return "suc";
    }
    /**
     * 用户退出登录
     * @param session
     * @return
     */
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();//清除session
        System.out.println("用户退出登录");
        return "login";
    }
}

登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h1> <font color="red"> <b th:text="${msg}"></b></font></h1>
<form action="/SSMDemo/login" method="post">
    账户:<input type="text" name="username"/>
    密码:<input type="password" name="password"/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

主页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello <b th:text="${msg}"></b></h1>
<a href="/SSMDemo/logout" rel="external nofollow"  >入门程序</a>
</body>
</html>

拦截器配置

/**
 * 登录拦截器
 */
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取请求url
        String url = request.getRequestURI();
        //非登录请求进行拦截
        if (!url.contains("login")){
            //非登录请求获取session
            if(request.getSession().getAttribute("user") != null){
                return true;//说明已经登录,放行
            }else { //没有登录,跳转到登录页面
                request.setAttribute("msg","您还没登录。请先登录。。。");
                request.getRequestDispatcher("/html/login.html").forward(request,response);
            }
        }else {
            return true; //登录请求,放行
        }
        return true;
    }
    //省略了postHandle()和afterCompletion()方法
}

在springMV.xml文件当中配置拦截器

<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/> <!--/**表示所有url-->
        <bean class="com.qcby.Interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

6.多个拦截器的执行流程

当多个拦截器同时工作时,它们的preHandle()方法会按照配置文件中拦截器的配置顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置顺序的反序执行。
假设有两个拦截器Interceptor1和interceptor2,并且在配置文件中,Interceptor1拦截器配置在前。

在这里插入图片描述

到此这篇关于SpringMVC请求、响应和拦截器的使用实例详解的文章就介绍到这了,更多相关SpringMVC请求、响应和拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文