• SpringMVC实训内容


    SpringMVC简介

    ​ springmvc是一个基于mvc模式的web框架,springmvc是spring框架中的一个模块,可以和spring框架无缝集成 。

    ​ mvc: m:model (模型–数据) v :view (视图)–页面 c:controller (控制层)–处理器-用来跳转返回相关数据

    ​ springmvc为什么要学习 ? 90%的招聘单位要求使用springmvc,以spring框架为核心 ,在表现层提供了一套优秀的解决方案 (数据接收,上传,下载,国际化)

    ​ springmvc是一个servlet ,纯正的servlet .

    springmvc的入门理论:

    ​ 使用springmvc必须先要保证有spring的环境,而且要保证spring ioc容器初始化 。

    ​ springmvc应用必须要导入spring相关的jar包 (核心jar包)–springmvc的核心jar包

    ​ spring-webmvc ----springmvc的核心包

    ​ spring-web ------spring框架对web项目的支持

    springmvc的核心控制器/前端控制器

    ​ 作用:主要是用来拦截请求,根据相关的规则分发请求到目标处理器 。

    SpringMVC核心流程

    在这里插入图片描述

    SpringMVC实际操作

    ​ 和servlet应用关联起来

    ​ 复习servlet的实现方式 : 两种方式 web.xml文件是web项目和服务器约定的最关键的文件。

    Servlet的实现方式

    第一种方式
    /**
     * servlet的第一种实现方式
     *
     */
    public class MyFirstServlet implements Servlet {
    
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("接收到请求~~");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    web.xml文件

        <!--servlet实现第一种方式配置 -->
        <servlet>
            <servlet-name>firstServlet</servlet-name>
            <servlet-class>cn.wolfcode.servlet.MyFirstServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>firstServlet</servlet-name>
            <url-pattern>*.do</url-pattern>  <!-- *.do   表示所有以.do结束的请求,也就是说这类请求会和web.xml文件进行匹配。
            首先会找到servlet-mapping  然后通过servlet-name交给指定的servlet-class进行处理-->
        </servlet-mapping>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    第二种方式(注解的方式)
    /**
     * servlet的第二种实现方式
     */
    @WebServlet("/second")
    public class MySecondServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MySecodeServlet-接收到请求");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Sprinmvc的实现方式

    第一种方式
    /**
     * 使用springmvcd的第一种实现方式
     */
    public class FirstHandler implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("FirstHandler--接收到请求");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public class SecondHandler implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("SecondHandler-接收到请求");
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    web.xml

        <servlet>
            <servlet-name>FirstHandler</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 此处必须是一个servlet核心控制器  -->
            <init-param> <!-- 初始化servlet-class  告诉其找类的时候不要去web目录下找  -->
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>FirstHandler</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    applicationContext.xml

        <bean id="/test.do" class="cn.wolfcode.handler.FirstHandler"></bean>
        <bean id="/test2.do" class="cn.wolfcode.handler.SecondHandler"></bean>
    
    • 1
    • 2
    第二种方式(注解的方式)
    @Controller // 有@Controller注解 就表示 这是一个处理器  相当于 实现了Controller接口
    public class ThridController {
    
        @RequestMapping("/req1.do")   // 该注解  相当于在applicationContext.xml文件中配置了一个bean
        public ModelAndView requestHandle(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求....");
            return null;
        }
    
        // 以前配置,实现Controller的方法  只能有一个处理器(一个链接),想要多建几个就必须多new几个类。而使用注解的方式
        // 想要几个处理器就加几个RequestMapping  一个RequestMapping就是一个处理器
        @RequestMapping("/req2.do")
        public ModelAndView requestHandle2(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求req2.do....");
            return null;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    web.xml

     <servlet>
            <servlet-name>FirstHandler</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param> <!-- 告诉 核心控制器 DispatcherServlet 到指定地方去找 -->
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext.xml</param-value>
            </init-param>
    <!--        启动参数:0 这个值越小 就越先初始化-->
            <load-on-startup>0</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>FirstHandler</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    applicationContext.xml(note:要使context标签在xml文件中可用还需要在头文件中配置相关的请求头)

     <!-- @Controller注解生效  Controller注解  只是把上面配置bean的步骤省了  浏览器来的请求也是从 web中的web.xml中去找  然后逐次跳转到此处再到具体的类 -->
        <context:component-scan base-package="cn.wolfcode.handler"/>
    
    • 1
    • 2

    SpringMVC跳转页面方式

    转发
    传统转发
     @RequestMapping("/req1.do")   // 该注解  相当于在applicationContext.xml文件中配置了一个bean
        public ModelAndView requestHandle(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求....");
            //转发操作
            try {
                //设置作用域数据(注意:先设置数据后跳转页面,因为跳转页面后再设置数据已经没有意义了)
                request.setAttribute("info","hello");
                //跳转  转发  跳转到jsp/fj.jsp这个页面
                request.getRequestDispatcher("jsp/fj.jsp").forward(request,resp);
                //后续执行的代码  需要和跳转的代码无关系  
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    SpringMVC转发
        @RequestMapping("/req2.do")
        public ModelAndView requestHandle2(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求req2.do....");
            //实现转发 
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("jsp/fj.jsp"); // 跳转到 jsp/fj.jsp这个页面
            //设置一个值
            modelAndView.addObject("info","world");
            return modelAndView;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    重定向
    传统重定向
        @RequestMapping("/req1.do")   // 该注解  相当于在applicationContext.xml文件中配置了一个bean
        public ModelAndView requestHandle(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求....");
            // 执行重定向
            try {
                // request.setAttribute("info","重定向携带数据"); // 一次请求生效
                request.getSession().setAttribute("info","session重定向携带数据");  // 重定向携带数据 .getSession().
                // resp.sendRedirect("jsp/fj.jsp");
                // 重定向到baidu.com
                resp.sendRedirect("https://www.baidu.com/");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    SpringMVC实现重定向
     @RequestMapping("/req2.do")
        public ModelAndView requestHandle2(HttpServletRequest request, HttpServletResponse resp){
            System.out.println("ThridController请求req2.do....");
            //实现重定向
            ModelAndView mav=new ModelAndView() ;
            mav.setViewName("redirect:jsp/fj.jsp");
    //        mav.addObject("info","springmvccho重定向");
            //不能够使用addObject这个方法
            // spring使用传统方式实现重定向携带数据
            request.getSession().setAttribute("info","spring使用传统方式实现重定向携带数据");
            return mav;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    note:WEB-INF里的页面是一个非常重要的核心资源,不可能轻易在外部被访问,故重定向不可以访问到(由用户决定),而转发可以访问到(由程序决定),这样也是出于安全考虑。

    视图解析器

    配置:在application.xml文件中配置 自己的视图解析器

        <!--配置视图解析器简化页面跳转  该class为视图解析器的核心类型  id可配可不配-->
        <bean   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--        suffix表示页面视图的后缀 -->
            <property name="suffix" value=".html"></property>
    <!--        prefix表示页面视图的前缀 -->
            <property name="prefix" value="WEB-INF/html/userhtml/"></property>
        </bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置以后实现转发:

    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("user");
    
    • 1
    • 2

    此时会转发到 WEB-INF/html/userhtml/.html页面,配置文件会自动将前缀后缀拼接上。

    note:视图解析器和重定向不能同时使用,即redirect关键字与视图解析器不能同时使用!

    使用转发的方式是否可以与视图解析器同时使用呢?

    可以,但是必须省略转发的关键字forward!其实转发和重定向都有一个关键字:

    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("forward:user"); // 转发 转发的关键字可以省略
    modelAndView.setViewName("redirect:user"); // 重定向
    
    • 1
    • 2
    • 3

    关于方法返回值

        @RequestMapping("/req4.do")
        public String requestHandle4(HttpServletRequest request, HttpServletResponse resp) {
            return "user" ; // 返回了一个对应的视图 (配置了上面所提的视图解析器)
            return "/req1.do"; // 返回了一个当前系统对应的请求路径(前面的代码有) (未配置上面所提的视图解析器)
            return "WEB-INF/html/userhtml/user.html";  // 完整资源的路径,找对应的资源 (未配置上面所提的视图解析器)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    当配置了视图解析器的时候,返回String类型只能表示访问对应的视图
    当没有配置视图解析器的时候,返回String类型表示当前系统对应的请求路径(处理器的请求路径/完整资源的路径)
    
    • 1
    • 2

    SpringMVC返回值之json

    键值对类型的数据才能转换为json
    利用ObjectMapper对象将键值对数据转换为json

    eg:

        @RequestMapping("/getjson.do")
        public String getjson1(HttpServletRequest req, HttpServletResponse resp){
            //实现将对象转换成json字符串
            //先创建一个ObjectMapper对象
            ObjectMapper objectMapper = new ObjectMapper();
            //创建一个待转换的对象
            Map<String,Object> resultMap=new HashMap<>() ;
            resultMap.put("code","1111") ;
            //转换
            String json_str=null ;
            try {
                 json_str = objectMapper.writeValueAsString(resultMap);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            req.setAttribute("info",json_str);
            return "jsp/fj.jsp";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    返回一个真正的json,不需要页面展示
        @ResponseBody
        @RequestMapping("/getjson2.do")
        public Map<String,Object> getjson2(HttpServletRequest req, HttpServletResponse resp){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            resultMap.put("code","9999");
            resultMap.put("msg","system error");
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    note:此处的@ResponseBody注解作用是将java对象转换为json格式的数据,同时也需要在applicationContext.xml配置文件中加入(以下两个都是为了启用@ResponseBody注解)

    添加mv约束:(因为mvc标签用不了)

    xmlns:mvc="http://www.springframework.org/schema/mvc"
    
    • 1

    mvc标签文件:

     <mvc:annotation-driven />
    
    • 1

    SpringMVC拦截规则

    eg: 满足json且满足restful风格

      <url-pattern>/*
    
    • 1
        /**
         *要求返回json
         * 同时满足restful风格
         * @param req
         * @param resp
         * @return
         */
        @ResponseBody
        @RequestMapping("/getjson3")
        public Map<String,Object> getjson3(HttpServletRequest req, HttpServletResponse resp){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            resultMap.put("code","9999");
            resultMap.put("msg","system error");
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    /* 表示所有的请求都会发送到前端处理器进行请求!实际开发中并不会这样使用,因为这样会导致所有的静态资源都交给了前端处理器进行处理,解决这个问题十分的麻烦。 一般使用:

      <url-pattern>/</url-pattern>
    
    • 1

    note:SpringMVC自带了静态资源处理器,故想直接在浏览器访问静态资源是不可能的。若想访问静态资源,则需要增加配置:

     <mvc:default-servlet-handler/>
    
    • 1

    该行配置表示不使用mvc自带的静态资源处理器,而是使用tomcat自带的资源处理器。

    #### SpringMVC接收简单参数类型
    
    • 1
    传统的方式
        /**
         * 传统方式接收参数
         * @param req
         * @param resp
         * @return
         */
        @ResponseBody
        @RequestMapping("/request1")
        public Map<String,Object> requestHandle1(HttpServletRequest req, HttpServletResponse resp){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //从保存请求信息的对象中获取req
            String name = req.getParameter("name");
            //打印
            System.out.println("接收到的数据:"+name);
            //设置返回值
            resultMap.put("data",name);
            //返回
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在请求头中 + ?name=luhua 的结果
    在这里插入图片描述
    多个参数就用&进行拼接!name=…&name=…&name=…

    SpringMVC接收简单参数类型
    /**
         * 使用springmvc接收简单参数类型
         *  而且要求实际传参-实参数名称和际使用的参数名称一致
         *  如果不一致,会导致无法接收到参数,此时会默认该值为NULL
         *  注意:
         * @param name
         * @param age
         * @return
         */
        @ResponseBody
        @RequestMapping("/request2")
        public Map<String,Object> requestHandle2(String name,Integer age){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //直接从请求参数中获取并打印
            System.out.println("接收到的数据:"+name+"---"+age);
            //设置返回值
            resultMap.put("name",name);
            resultMap.put("age",age);
            //返回
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    @RequestParam()注解 修饰处理器中的形式参数 由SpringMVC提供,具体解释如下:
     /**
         * 接收参数参数名称和实际使用的参数名称不一致
         * @RequestParam()中的属性   name=value --表示形参的别名(处理器/接口对外暴露的参数名称)
         *                          required =true 必传   =false 非必传  默认必传
         * @param uname
         * @param uage
         * @return
         */
        @ResponseBody
        @RequestMapping("/request3")
        public Map<String,Object> requestHandle3(@RequestParam(value ="nn")String uname,
                                                 @RequestParam(value="a",required = true)Integer uage){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //直接从请求参数中获取并打印
            System.out.println("接收到的数据:"+uname+"---"+uage);
            //设置返回值
            resultMap.put("name",uname);
            resultMap.put("age",uage);
            //返回
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    SpringMVC接收参数乱码问题
        <%--    action表示请求后端的请求的具体的接口是什么--%>
         <form method="post" action="../request4">
             <input type="text" name="uname"/>
             <input type="text" name="uage"/>
             <input type="submit" value="提交" />
         </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     /**
         * 接收post请求
         * 1.form表单中action属性值../相对路径,解决了404问题
         * 2.使用处理器可以接收到post请求
         * 3.接收到post请求出现了乱码
         * 4.乱码问题怎么解决?
         *     回顾之前的get请求并没有出现乱码情况
         *     现在post请求为什么就出现乱码了?
         *  5.get请求实际上也出现了乱码只是被tomcat8.0+解决了 tomcat8一下版本没有解决
         *  6.如果项目上要求使用tomcat 7  ,get请求的乱码无法解决了嘛?
         *     怎么解决?在tomcat 7中添加了URIEncoding="utf-8"
         *   7.post请求乱码怎么办?
           springmvc提供了解决方案,在web.xml文件中配置一个解决乱码的配置文件  配置一个过滤器
         *    8.通用的乱码解决方案(get/post)
         *
         * @param uname
         * @param uage
         * @return
         */
        @ResponseBody
        @RequestMapping("/request4")
        public Map<String,Object> requestHandle4(@RequestParam(value ="uname")String uname,
                                                 @RequestParam(value="uage")Integer uage){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //直接从请求参数中获取并打印
            System.out.println("接收到的数据:"+uname+"---"+uage);
    
            //将接收到的乱码的数据进行转换
            try {   // 如果直接在浏览器中输入  /request4这个地址 会出现400错误  原因在于uname此时一直为null值 故不可能存在.getBytes
                // 故出现报错:  Required request parameter 'uname' for method parameter type String is not present]
                byte[] bytes = uname.getBytes("ISO-8859-1");
                //将字节数组进行重新编码
                String str=new String(bytes,"utf-8") ;
                System.out.println("转码之后的字符串:"+str);
                resultMap.put("name",str);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            //设置返回值
            resultMap.put("age",uage);
            //返回
            return resultMap ;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    出现乱码的原因:数据在传输的过程中,编码发生改变,导致前后编码不一样故出现了乱码。

    SpringMVC解决乱码问题

    方式1:在web.xml文件中配置一个过滤器 /* 表示所有的请求

    <!--    springMVC提供的过滤器-->
        <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
        <filter-mapping>
            <filter-name>encoding</filter-name>
            <url-pattern>/*
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    方式2:无SpringMVC框架的情况下解决乱码问题! 通用的乱码解决方案

     			//此处接收到的数据是 uname
    			//将接收到的乱码的数据进行转换 此处的ISO-8859-1为已知的数据的编码格式
    			byte[] bytes = uname.getBytes("ISO-8859-1"); // 将其转换为其对应的编码格式的字符数组
                 //将字节数组进行重新编码
                 String str=new String(bytes,"utf-8") ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    接收复杂的数据类型

    数组这种复杂的数据

     <form method="post" action="../request5"> <%-- action使其对应到一个具体的  处理器 --%>
            游泳:<input type="checkbox"  name="hobby" value="游泳"/>
            下棋:<input type="checkbox"  name="hobby" value="下棋"/>
            登山:<input type="checkbox"  name="hobby" value="登山"/>
            打球:<input type="checkbox"  name="hobby" value="打球"/>
            <input type="submit"  value="提交" />
        </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
        @ResponseBody
        @RequestMapping("/request5")
        public Map<String,Object> requestHandle5(@RequestParam(value = "hobby")String[] hobby){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //打印接收到的参数
            System.out.println(Arrays.toString(hobby));
            //设置返回值
            resultMap.put("code",9999);
            //返回
            return resultMap ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    用数组的类型去接收hobby这些数据。

    SpringMVC接收实体类参数

    使用实体类匹配对应参数

    1.需求: 接收一个人的信息(注册)– 用户在网页上填写个人信息

    jsp前端页面:

        ```java
    
    • 1
    姓名:
    生日:
    身份证:
    手机号码:
    ```

    定义一个对应的实体类,去跟请求参数匹配:

    /**
     * 跟request6中的请求参数匹配
     */
    public class UserInfo {
    
        private String uname ;
        //private Integer uage ;
        private String idcard ;
        private String uphone ;
        @DateTimeFormat(pattern ="yyyy-MM-dd" )
        private Date birthday ;
        ..................................................
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
     	@ResponseBody
    	@RequestMapping("/request6")
        public Map<String,Object> requestHandle6(UserInfo userInfo){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //打印接收到的参数
            System.out.println(userInfo);
            Date birthday = userInfo.getBirthday();
            //设置返回值
            resultMap.put("code",9999);
            //返回
            return resultMap;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    note:

    1. @RequestParam不能应用于实体类中
    2. 使用实体类接收post请求中的参数也是可行的。
    3. 如果使用字符类型接收–该参数值且是中文,一定不能出现乱码,否则会报400
    4. @DateTimeFormat(pattern =“yyyy-MM-dd” ) 该注解是由SpringMVC提供用于将满足这样规范——yyyy-MM-dd的字符串类型转换为Date类型的数据。(因为在浏览器中输入的数据都是字符串类型)。注意该注解只能修饰与时间相关的类型。
    数据回显

    需求:注册用户后,需要展示用户的信息

        <form method="post" action="../request6">
            姓名:<input type="text" name="uname" /> <br/>
            生日:<input type="date" name="birthday" /><br/>
            身份证:<input  type="text" name="idcard"/><br/>
            手机号码:<input type="text" name="uphone"/><br/>
            <input type="submit" value="提交"/>
        </form>
        <hr/>
             <h2>${user.uname}</h2>
             <h2>${user.idcard}</h2>
             <h2>${user.uphone}</h2>
             <h2>${user.birthday}</h2>
        <hr/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
     @RequestMapping("/request6")
        public String requestHandle6(@ModelAttribute("user") UserInfo userInfo){
            //先存放用于保存键值对的map集合
            Map<String,Object> resultMap=new HashMap<String,Object>() ;
            //打印接收到的参数
            System.out.println(userInfo);
            Date birthday = userInfo.getBirthday();
            //设置返回值
            resultMap.put("code",9999);
            //返回
            return "jsp/fj.jsp" ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    note:@ModelAttribute(“user”) 该注解的意思将参数userInfo简化为user(故在上面的前端代码中使用的是user而不是userInfo)(自我感觉是内部简化因为是在代码内部调用的)!

    文件上传

    传统方式

    实际操作:IO流 读数据写数据的过程

    <h2>文件上传</h2>
        <form action="../uploadfile" method="post" enctype="multipart/form-data">
            <input  type="file"  name="myfile" value="选择文件"/>
            <input type="submit" value="上传提交"/>
        </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.所有文件上传都是采用post的方式;2.enctype="multipart/form-data"在使用包含文件上传控件的表单时必须使用该值

      /**
         * 文件上传
         * @param req
         * @return
         */
        @ResponseBody  // 不加该注解表示返回一个Map集合的这种类型的视图,但是没有就会报错,故需加该注解 
        @RequestMapping("/uploadfile")
        public Map<String, Object> uploadFile(HttpServletRequest req) {
            //定义map集合
            Map<String,Object> resultMap=new HashMap<>() ;
            ServletInputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                inputStream = req.getInputStream();
                // 此处写死了 
                outputStream = new FileOutputStream(new File("C:\\Users\\LuoTianYang\\Desktop\\uploadDir\\xx.jpg"));
                //定义一个byte数组
                byte[] b = new byte[1024];
                //读取到的长度
                int len = 0;
                //判断 如果read为-1那么表示数据读取完成
                while ((len = inputStream.read(b)) != -1) {
                    //写的过程
                    outputStream.write(b, 0, len);
                }
                //关闭流
                outputStream.close();
                inputStream.close();
                outputStream.flush();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            resultMap.put("code","success") ;
            return resultMap;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    以上是传统的方式实现文件的上传,会出现实际上传保存后的文件会比原来的文件更大,因为在使用req.getInputStream();流的时候会将前端的一些标签流也获得,从而造成文件更大而无法正常打开。

    SpringMVC的方式
    <h2>文件上传</h2>
        <form action="../uploadfile" method="post" enctype="multipart/form-data">
            <input  type="file"  name="myfile" value="选择文件"/>
            <input type="submit" value="上传提交"/>
        </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
       @ResponseBody
        @RequestMapping("/uploadfile")  // MultipartFile 使用文件上传的对应的那个部件  myfile是与控件中的名称保持一致
        public Map<String, Object> uploadFile(MultipartFile myfile) {
            //定义map集合
            Map<String,Object> resultMap=new HashMap<>() ;
            //获取文件写文件到本地磁盘
            try {
                InputStream inputStream = myfile.getInputStream();
                // myfile.getOriginalFilename() 上传的文件是什么名称,它保存后的文件就是什么名称
                OutputStream outputStream=new FileOutputStream(new  File("C:\\Users\\LuoTianYang\\Desktop\\uploadDir\\"+myfile.getOriginalFilename())) ;
                //边读边写的
                byte[] b=new byte[1024];
                //定义长度
                int len= 0 ;
                while( (len=inputStream.read(b))!=-1 ){
                    outputStream.write(b,0,len);
                }
                outputStream.flush();
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            resultMap.put("code","success") ;
            return resultMap;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    note:上述代码中用了MultipartFile多媒体请求,该请求需要加一个额外的配置

       <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        </bean>
    
    • 1
    • 2

    文件下载

        <h2>文件下载</h2>
         <a href="../download?filename=xx.jpg">下载图片a</a>
        <a href="../download?filename=短视频_俏.mp4">下载视频b</a>
    
    • 1
    • 2
    • 3
     /**
         * 下载
         * @param filename
         * @param req
         * @param resp
         * @return
         */
        @ResponseBody
        @RequestMapping("/download")
        public void downloadFile(String filename,HttpServletRequest req, HttpServletResponse resp){
            //定义一个返回值
            Map<String,Object> resultMap=new HashMap<>() ;
            //设置响应的名称,文件叫什么名字
            resp.setHeader("Content-Disposition","filename="+filename);
            //设置文件类型
            resp.setHeader("Content-Type","application/mp4");
    
            //从服务器端磁盘中找到需要下载的文件
            //目前在服务端提供的下载的资源目录
            String dir="C:\\Users\\LuoTianYang\\Desktop\\uploadDir\\" ;
            //拼接一个需要下载的文件的路径
            String fileurl=dir+filename ;
            //创建一个文件对象
            File file=new File(fileurl) ;
            //判定file是否存在
            if(file.exists()){
                //存在--就下载
                try {
                    //读取这个文件到内存中
                    InputStream input=new FileInputStream(file);
                    //创建一个输出流
                    ServletOutputStream output = resp.getOutputStream();
                    //边读边写
                    byte[] b=new byte[2048];
                    //定义长度
                    int len=0 ;
                    while(  (len=input.read(b)) != -1){
                        output.write(b,0,len);
                    }
                    //关闭流
                    output.flush();
                    output.close();
                    input.close();
                    //设置返回值
                    resultMap.put("code",1000);
                    resultMap.put("msg","下载成功");
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    resultMap.put("code",1001);
                    resultMap.put("msg","文件不存在");
                } catch (IOException e) {
                    e.printStackTrace();
                    resultMap.put("code",1002);
                    resultMap.put("msg","输入输出异常");
                }
    
            }else{
                //不存在
                resultMap.put("code",1001);
                resultMap.put("msg","文件没找到");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    note:

    1. 以流的形式进行响应(resp.getOutputStream())就不能在方法中再添加返回值,否则会报错。
    2. 通过上述的文件上传/下载可知,其实核心就是javaSE中IO流的内容,只是有了部分的API发生了改变。
  • 相关阅读:
    Java 中模板下载
    【算法】PTA刷题记录
    Tableau2——折线图,饼图
    echarts-饼图和 模拟事件补充
    GZ033 大数据应用开发赛题第07套
    stream流—关于Collectors.toMap使用详解
    【Linux】探索环境变量与C语言命令行参数处理
    Guava限流器原理浅析
    实验32:气压温度传感器实验
    智能咖啡厅助手:人形机器人 +融合大模型,行为驱动的智能咖啡厅机器人
  • 原文地址:https://blog.csdn.net/ailaohuyou211/article/details/126275830