framework学习笔记day12---SpringMVC

Restful风格介绍

  • WebAPI

    • 如果一个URL返回的不包含HTML,而是数据,那么这个URL就是一个WebAPI(web接 口)
  • Restful

    • 按照Rest风格访问WebAPI的一种方式
  • Restful风格

    • ①不同CRUD操作采用不同的请求方式
    • ②后台的响应数据采用JSON格式

HiddenHttpMethodFilter过滤器

  • 概述

    • form表单只支持get、post请求,如果要支持put、delete就需要使用HiddenHttpMethodFilter过滤器
  • 代码实现

    <!--post 2 put-->
    <form th:action="@{/rest/post2Put}" method="post">
        <input type="hidden" name="_method" value="put">
        消息:<input type="text" name="msg"><br>
        <button type="submit">提交</button>
    </form>
    
    <!--post 2 delete-->
    <form th:action="@{/rest/post2Delete}" method="post">
        <input type="hidden" name="_method" value="delete">
        消息:<input type="text" name="msg"><br>
        <button type="submit">提交</button>
    </form>
    
    //@RequestMapping(path = "/rest/post2Put",method = RequestMethod.PUT)
    @PutMapping("/rest/post2Put")
    public String post2Put(String msg){
        System.out.println("msg = " + msg);
        return "demo01";
    }
    
    @DeleteMapping("/rest/post2Delete")
    public String post2Delete(String msg){
        System.out.println("msg = " + msg);
        return "demo01";
    }
    
  • 注意事项

    • 只能使用post模拟put、delete

Restful风格查询用户

  • 需求

    • 根据id查询用户记录
  • 分析

    http://localhost:8080/framework27/user/selectUserById?id=1 : 之前
    http://localhost:8080/framework27/user/1 : 现在 , GET请求
    
  • 代码实现

    <a th:href="@{/user/1}">Restful风格查询用户</a>
    
    @GetMapping("/user/{userId}")
    public String selectUserById(@PathVariable Integer userId){
        System.out.println("userId = " + userId);
        return "demo02";
    }
    

Restful风格删除用户

  • 需求

    • 根据id删除用户记录
  • 分析

    http://localhost:8080/framework27/user/deleteUserById?id=1 : 之前
    http://localhost:8080/framework27/user/1 : 现在 , DELETE请求
    
  • 代码实现

    @DeleteMapping("/user/{userId}")
    public String deleteUserById(@PathVariable Integer userId){
        System.out.println("deleteUserById userId = " + userId);
        return "demo02";
    }
    
    <body>
    
    
    <div id="app">
    
        <!--post 2 delete-->
        <form method="post" id="deleteUserForm">
            <input type="hidden" name="_method" value="delete">
    
        </form>
    
        <a id="myA" th:href="@{/user/1}" @click.prevent="deleteUserById()">Restful风格删除用户</a>
    </div>
    
    
    </body>
    <script th:src="@{/js/vue.js}"></script>
    <script>
    
    
        //3,form表单根据a标签的href属性值发起请求
        var vue = new Vue({
            el: "#app",
            data: {},
            methods: {
                //1,点击a标签
                deleteUserById() {
                    console.log("deleteUserById");
                    //2,触发form表单
                    var formEle = document.getElementById("deleteUserForm");
                    var aEle = document.getElementById("myA");
                    //3,form表单根据a标签的href属性值发起请求
                    formEle.setAttribute("action", aEle.getAttribute("href"));
                    formEle.submit();
                }
            }
        })
    
    
    </script>
    

Restful风格添加用户

  • 需求

    • 添加用户记录
  • 分析

    http://localhost:8080/framework27/user/addUser?userName=root&userPwd=root : 之前 
    http://localhost:8080/framework27/user?userName=root&userPwd=root: 现在 , POST请求
    
  • 代码实现

    @PostMapping("/user")
    public String addUser(User inputUser){
        System.out.println("addUser user = " + inputUser);
        return "demo04";
    }
    
    <form th:action="@{/user}" method="post" >
        <input type="text" name="userName" ><br>
        <input type="text" name="userPwd" ><br>
        <input type="submit" value="提交">
    </form>
    

Restful风格登录功能

  • 需求

    • 登录功能
  • 分析

    http://localhost:8080/framework27/user/login?userName=root&userPwd=root : 之前,post
    http://localhost:8080/framework27/user?userName=root&userPwd=root: 现在 , POST请求
    
  • 代码实现

    @PostMapping("/user/login")
    public String login(User inputUser){
        System.out.println("login user = " + inputUser);
        return "demo05";
    }
    
    <form th:action="@{/user/login}" method="post" >
        <input type="text" name="userName" ><br>
        <input type="text" name="userPwd" ><br>
        <input type="submit" value="提交">
    </form>
    

Restful风格修改用户功能

  • 需求

    • 根据id修改用户记录
  • 分析

    http://localhost:8080/framework27/user/updateUserById?userId=1&userName=root&userPwd=root : 之前,post
    http://localhost:8080/framework27/user?userId=1&userName=root&userPwd=root : 现在 , PUT请求
    
  • 代码实现

    @PutMapping("/user")
    public String updateUserById(User inputUser){
        System.out.println("updateUserById user = " + inputUser);
        return "demo04";
    }
    
    <form th:action="@{/user}" method="post" >
        <input type="hidden" name="_method" value="put">
        <input type="hidden" name="userId" value="250">
        <input type="text" name="userName" ><br>
        <input type="text" name="userPwd" ><br>
        <input type="submit" value="提交">
    </form>
    

SpringMVC获取AJAX发送的普通参数

  • 代码实现

    <body>
    <div id="app">
        <form th:action="@{/ajax/getParamter}" method="post" @submit.prevent="getParamter()">
    
            <input type="text" name="userName" v-model="user.userName"><br>
            <input type="text" name="userPwd" v-model="user.userPwd"><br>
            <input type="submit" value="提交">
        </form>
    </div>
    
    </body>
    <script th:src="@{/js/axios.js}"></script>
    <script th:src="@{/js/vue.js}"></script>
    <script>
    
        var vue = new Vue({
            el: "#app",
            data: {
                user: {
                    userId: 500,
                    userName: "",
                    userPwd: ""
                }
            },
            methods: {
                getParamter() {
                    var _this = this;
                    //发起异步请求 /ajax/getParamter
                    axios({
                        method: "get",
                        url: "/framework27/ajax/getParamter",
                        params: {
                            userId: _this.user.userId,
                            userName: _this.user.userName,
                            userPwd: _this.user.userPwd
                        }
                    }).then(function (res) {
                        var data = res.data;
                        console.log(data);
    
                    })
                }
            }
        })
    
    </script>
    
    @RequestMapping("/ajax/getParamter")
    public void getParamter(User user, HttpServletResponse response) throws IOException {
        System.out.println("user = " + user);
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //resultVO 2 json字符串
        response.setContentType("application/json;charset=utf-8");
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        response.getWriter().write(jsonStr);
    }
    

SpringMVC获取AJAX发送的请求体json

  • 代码实现1

    <body>
    <div id="app">
        <form th:action="@{/ajax/getParamter}" method="post" @submit.prevent="getParamter()">
            <!--<input type="hidden" name="userId" value="250" v-model="user.userId">-->
            <input type="text" name="userName" v-model="user.userName"><br>
            <input type="text" name="userPwd" v-model="user.userPwd"><br>
            <input type="submit" value="提交">
        </form>
    </div>
    
    </body>
    <script th:src="@{/js/axios.js}"></script>
    <script th:src="@{/js/vue.js}"></script>
    <script>
    
        var vue = new Vue({
            el: "#app",
            data: {
                user: {
                    userId: 500,
                    userName: "",
                    userPwd: ""
                }
            },
            methods: {
                getParamter() {
                    var _this = this;
                    //发起异步请求 /ajax/getParamter
                    axios({
                        method: "post",
                        url: "/framework27/ajax/getParamter2",
                        data: {
                            userId: _this.user.userId,
                            userName: _this.user.userName,
                            userPwd: _this.user.userPwd
                        }
                    }).then(function (res) {
                        console.log(res);
                    })
                }
            }
        })
    
    </script>
    
    @RequestMapping("/ajax/getParamter2")
    public void getParamter2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        BufferedReader bufferedReader = request.getReader();
        String content = null;
        StringBuffer sb = new StringBuffer();
        while ((content = bufferedReader.readLine()) != null) {
            sb.append(content);
        }
        String inputJsonStr = sb.toString();
        //②jsonStr 2 javabean
        User user = new ObjectMapper().readValue(inputJsonStr, User.class);
        System.out.println("user = " + user);
    
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //resultVO 2 json字符串
        response.setContentType("application/json;charset=utf-8");
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        response.getWriter().write(jsonStr);
    }
    
  • 代码实现2

    @RequestMapping("/ajax/getParamter3")
    public void getParamter3(@RequestBody String inputJsonStr, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        System.out.println("inputJsonStr = " + inputJsonStr);
        //② jsonStr2 javabean
        User user = new ObjectMapper().readValue(inputJsonStr, User.class);
        System.out.println("user = " + user);
    
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //resultVO 2 json字符串
        response.setContentType("application/json;charset=utf-8");
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        response.getWriter().write(jsonStr);
    }
    
  • 代码实现3(推荐)

    @RequestMapping("/ajax/getParamter4")
    public void getParamter4(@RequestBody User user, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        //②jsonStr 2 javabean
        System.out.println("user = " + user);
    
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //resultVO 2 json字符串
        response.setContentType("application/json;charset=utf-8");
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        response.getWriter().write(jsonStr);
    }
    

SpringMVC响应json字符串

  • 概述

    • @ResponseBody : 将Handler方法的返回值作为响应正文返回给浏览器;如果返回值是一个javabean对象会自动将其转换为json字符串;同时也解决响应正文中文乱码问题。
  • 代码实现1

    @RequestMapping("/ajax/testResponse1")
    public void testResponse1(@RequestBody User user, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        //②jsonStr 2 javabean
        System.out.println("user = " + user);
    
        response.setContentType("application/json;charset=utf-8");
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //① resultVO 2 json字符串
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        //② json字符串作为响应正文返回给客户端
        response.getWriter().write(jsonStr);
    }
    
  • 代码实现2

    @ResponseBody
    @RequestMapping("/ajax/testResponse2")
    public String testResponse2(@RequestBody User user, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        //②jsonStr 2 javabean
        System.out.println("user = " + user);
    
        ResultVO resultVO = new ResultVO(true, "操作成功!", null);
        //① resultVO 2 json字符串
        String jsonStr = new ObjectMapper().writeValueAsString(resultVO);
        //② json字符串作为响应正文返回给客户端
        return jsonStr;//以前,默认应该是逻辑视图名称;返回是一个json字符串并且是响应正文。
    }
    
  • 代码实现3(推荐)

    @ResponseBody
    @RequestMapping("/ajax/testResponse3")
    public ResultVO testResponse3(@RequestBody User user, HttpServletResponse response) throws IOException {
        //①读取请求正文json
        //②jsonStr 2 javabean
        System.out.println("user = " + user);
        return new ResultVO(true, "操作成功!", null);//以前,默认应该是逻辑视图名称;返回是一个json字符串并且是响应正文。
    }
    

异常映射概述

  • 概述
    • 一个项目中会包含很多个模块,各个模块需要分工完成。如果张三负责的模块按照 A 方案处 理异常,李四负责的模块按照 B 方法处理异常……各个模块处理异常的思路、代码、命名细 节都不一样,那么就会让整个项目非常混乱。
    • 将异常类型和某个具体的视图关联起来,建立映射关系。可以通过 SpringMVC 框架来帮助 我们管理异常。
  • 好处
    • 让异常控制和核心业务解耦,二者各自维护,结构性更好
    • 整个项目层面使用同一套规则来管理异常

注解开发异常处理器

  • 以前

    @RequestMapping("/exception/testException1")
    public String testException1(int num) {
        try {
            if (num == 1) {
                String str = null;
                System.out.println(str.length());
    
            } else if (num == 2) {
                System.out.println(1 / 0);
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
            return "error1";
        } catch (ArithmeticException e) {
            e.printStackTrace();
            return "error2";
        }
        return "index";
    }
    
  • 现在

    @RequestMapping("/exception/testException2")
    public String testException2(int num) {
        if (num == 1) {
            String str = null;
            System.out.println(str.length());
        } else if (num == 2) {
            System.out.println(1 / 0);
        }
        return "index";
    }
    
    @ControllerAdvice
    public class MyExceptionAdvice {
    
    
        @ExceptionHandler(NullPointerException.class)
        public String handleNullPointerException(){
            System.out.println("MyExceptionAdvice handleNullPointerException");
            return "error1";
        }
    
        @ExceptionHandler(ArithmeticException.class)
        public String handleArithmeticException(){
            System.out.println("MyExceptionAdvice handleArithmeticException");
            return "error2";
        }
    
    
    }
    

异常处理解决方案

  • 代码实现

    @ResponseBody
    @RequestMapping("/exception/testException3")
    public ResultVO testException3(int num) {
        try {
            if (num == 1) {
                String str = null;
                System.out.println(str.length());
            } else if (num == 2) {
                System.out.println(1 / 0);
            } else if (num == 3) {
                //业务异常 (用户输入有问题) ,比如:输入为空、格式不对...
                throw new MyBusinessException("你老实点~~~");
            }
        } catch (ArithmeticException e) {
            e.printStackTrace();
            throw new MySystemException("系统异常!");
        } catch (NullPointerException e) {
            e.printStackTrace();
            throw new MySystemException("系统异常!");
        }
        return new ResultVO(true, "操作成功!", null);
    }
    
    @ControllerAdvice
    public class MyExceptionAdvice {
    
        @ResponseBody
        @ExceptionHandler(MyBusinessException.class)
        public ResultVO handleBusinessException(Exception e) {
            //提示用户
            return new ResultVO(false, "操作失败!", e.getMessage());
        }
    
    
        @ResponseBody
        @ExceptionHandler(MySystemException.class)
        public ResultVO handleSystemException(Exception e) {
            //安抚用户
    
            //发送消息给开发人员
    
            //记录日志
            return new ResultVO(false, "操作失败!", e);
        }
    
    }
    

Spring、MyBatis、SpringMVC整合

  • 开发步骤

    • ①引入相关依赖

    • ②Spring+MyBatis (mapper接口代理)

      • 1.1,定义service接口及其实现子类
      • 1.2,定义mapper接口
      • 1.3,编写spring-core.xml
        • 扫描注解
        • 扫描所有的mapper接口代理对象
        • 配置SqlSessionFactoryBean
        • 配置DruidDataSource
      • 1.4,测试通过
    • ③整合SpringMVC

      • 方式一,编写web.xml
        • 配置DispatcherServlet
          • 加载spring-mvc.xml
        • 配置ContextLoaderListener
          • 加载spring-core.xml
      • 方式二,编写web.xml
        • 配置DispatcherServlet
          • 加载spring-mvc.xml
          • 加载spring-core.xml
    • 整合SpringMVC

      <!--方式一-->
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring-core.xml</param-value>
      </context-param>
      
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
      
      <servlet>
          <servlet-name>mvc</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:spring-mvc.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
          <servlet-name>mvc</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
      
      <!--方式二-->
      <servlet>
          <servlet-name>mvc</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:spring-*.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
          <servlet-name>mvc</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
      

上一篇:SpringMVC-ResponseStatus注解的使用以及异常的处理


下一篇:Python 学习笔记 基本数据类型内置方法 之 序列类型