• SpringMVC-Day2


    第一章:响应数据和结果视图

    新建模块springmvc_day02_01_response

    1. 返回值分类

      1. 返回字符串

        1). Controller中的方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址

        2). 具体的应用场景

    response.jsp中点击对应方法mapping的超链接:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="user/testString">testString</a>
    </body>
    </html>

    ControllerUser.java

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/testString")
        public String testString(Model model){
            System.out.println("testString方法执行...");
            // 模拟从数据库中查询出User对象
            User user = new User();
            user.setUsername("张三");
            user.setPassword("123");
            user.setAge(30);
            //model对象  // 底层会存储到!request域!对象中,域中会显示有这么一个键值对
            model.addAttribute("user",user);
            return "success";
        }
    }

    点击超链接,服务器执行方法后根据视图解析器跳转到返回值success.jsp  设置允许el表达式

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>成功</title>
    </head>
    <body>
        <h3>执行成功</h3>
        <p>从request域中拿值:<br>
            用户名: ${user.username}<br>
            密码:${user.password} </p>
    
    </body>
    </html>

      2. 返回值是void(没有视图解析器的事儿了。。手动写转发。。

        1). 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到

    (可以用原生Servlet的API,就是传入HttpServletRequest req和res为参数,然后用req.getRequestDispatcher("/WEB-INF/pages/success.jsp").forword(req,res); 转发到对应路径。

    这个路径作为转发的话就不用写项目名称啥的,是在服务器端的转发,直接写从当前找***.jsp的路径。如果是res的重定向就是二次请求,是浏览器端的,需要写全路径获取虚拟目录,一般用req.getContextPath()+"***.jsp"。)

          1. 默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。

           2. 可以使用请求转发或者重定向跳转到指定的页面

        @RequestMapping("/testVoid")
        public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("testVoid方法执行了...");
            //1. 编写请求转发的程序
             request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
    
            // 2.或者重定向
             response.sendRedirect(request.getContextPath()+"/index.jsp");
    
            // 设置中文乱码
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            // 3.或者不用跳转直接会进行响应 
            response.getWriter().print("你好");
    
            return;
        }

    运行结果:在response.jsp里面点链接会跳转

      3. 返回值是ModelAndView对象(也是使用视图解析器跳转,跟返回字符串差不多的写法,返回字符串那个底层也会用到ModelAndView对象)

        1). ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

        2). 具体的代码如下

        /**
         * 返回ModelAndView
         * @return
         */
        @RequestMapping("/testModelAndView")
        public ModelAndView testModelAndView(){
            // 创建ModelAndView对象
            ModelAndView mv = new ModelAndView();
            System.out.println("testModelAndView方法执行了...");
            // 模拟从数据库中查询出User对象
            User user = new User();
            user.setUsername("李四");
            user.setPassword("456");
            user.setAge(30);
    
            // 把user对象存储到mv对象中,也会把user对象存入到request对象
            mv.addObject("user",user);
    
            // 跳转到哪个页面
            mv.setViewName("success");
            return mv;
        }

    运行结果:点击链接后跳转到success.jsp

    2. SpringMVC框架提供的转发和重定向

      1. forward请求转发

        1). controller方法返回String类型,想进行请求转发也可以编写成

      2. redirect重定向

        1). controller方法返回String类型,想进行重定向也可以编写成

        /**
         * 使用关键字的方式进行转发或者重定向
         * @return
         */
        @RequestMapping("/testForwardOrRedirect")
        public String testForwardOrRedirect(){
            System.out.println("testForwardOrRedirect方法执行了...");
            // 请求的转发 forward是关键字,此时也不能使用视图解析器了
    //         return "forward:/WEB-INF/pages/success.jsp";
    
            // 重定向 redirect是关键字 这里的重定向底层已经把项目名加上了 
            // (但是重定向无法获取里面的jsp?只能在webapp包下的??
            return "redirect:/index.jsp";
        }

    3. ResponseBody响应json数据

    首先搭建一个ajax异步的环境。(ajax就是按住大部分网页不动也不用等待服务器啥的,只对小部分进行与服务器的交互比如接收服务器的数据,大部分不用等小部分。。。

      webapp下面新建js包,把jquery.min.js拷贝到js文件夹下面。在response.jsp里面引入,然后写点击按钮发送异步请求。

    response.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <script src="js/jquery.min.js"></script>
        <script>
            // 页面加载,绑定单击事件
            $(function(){
                $("#btn").click(function(){
                    // alert("hello btn");
                    // 发送ajax请求
                    $.ajax({
                        // 编写json格式的字符串,设置属性和值
                        url:"user/testAjax",//后台这里对应路径的方法就可以执行了!!!
                        contentType:"application/json;charset=UTF-8",
                        data:'{"username":"zhangsan","password":"123","age":30}',
                        dataType:"json",
                        type:"post",
                        success:function(data){//回调函数!!success后执行
                            // data服务器端响应的json的数据,进行解析
                            alert(data);
                            alert(data.username);
                            alert(data.password);
                            alert(data.age);
                        }
                    });
                });
            });
        </script>
    
    </head>
    <body>
        <a href="user/testString">testString</a>
        <br>
        <a href="user/testVoid">testViod</a>
        <br>
        <a href="user/testModelAndView">testModelAndView</a>
        <br>
        <a href="user/testForwardOrRedirect">testForwardOrRedirect</a>
        <br>
    <%--button的mapping写在scrpit的ajax绑的那里--%>
        <button id="btn">发送ajax的请求</button>
        </body>
        </html>

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

        1). mvc:resources标签配置不过滤

          1. location元素表示webapp目录下的包下的所有文件

          2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b

        <!--告诉前端控制器,哪些静态资源不要拦截 js下面的-->
        <!-- 设置静态资源不过滤 -->    
        <mvc:resources location="/css/" mapping="/css/**"/>  <!-- 样式 -->    
        <mvc:resources location="/images/" mapping="/images/**"/>  <!-- 图片 -->    
        <mvc:resources location="/js/" mapping="/js/**"/>  <!-- javascript -->

      2. 使用@RequestBody获取请求体数据

        @RequestMapping("/testAjax")
        public void testAjax(@RequestBody String body){
            System.out.println("testAjax方法执行了...");
            System.out.println(body);}

      运行结果:就跟之前day1的一样。。。这里忘复制了。。。

      3. 使用@RequestBody注解把json的字符串转换成JavaBean的对象(需要在jsp中json类型的data的key值与属性名一致,需要依赖一个jar包jackson,就是json与javabean相互转换的那个,在pom中引入坐标,3个!!!)

        <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>

      controller中改String为User对象由于前端传的json的key与属性是对应的,所以可直接获取和打印了

        @RequestMapping("/testAjax")
        public void testAjax(@RequestBody User user){
            System.out.println("testAjax方法执行了...");
            // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
            System.out.println(user);}

      4. 使用@ResponseBody注解!!!把JavaBean对象转换成json字符串,直接响应

        1). 要求方法需要返回JavaBean的对象

    写有返回值的可以响应给前端,把从前端异步接收的json转成对象拿到后,经过服务器修改,又响应返回给前端以json显示。

        @RequestMapping("/testAjax")
        public @ResponseBody User testAjax(@RequestBody User user){//请求体,响应体 两个注解!!!!3个jar包!完成互相转换!!!
            System.out.println("testAjax方法执行了...");
            // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
            System.out.println(user);
            // 做响应,模拟查询数据库
            user.setUsername("lisi");
            user.setAge(40);
            // 做响应
            return user;
        }

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

    运行结果:

    前端response.jsp 在异步请求里发的json数据是zhangsan,123,30,

    然后到达服务器方法里成功通过@RequestBody和jackson拿到了封装好前端传来数据的User

    服务器中改了这个User的部分数据,然后通过@ResponseBody注解和3个jar包又响应给前端

    前端回调函数果然显示的是已经被服务器改掉了的json数据,没改的密码就还没变,名字年龄变化了。

    这个其实课题也有用,因为服务器给客户端传最终的定位坐标数据应该也是异步的,不影响其他。(比如这里是点击按钮接受一个异步的数据由弹窗获得,而我的课题是走一步触发新的定位数据到方法里,然后方法调业务层方法计算出数据返回给客户端!就看要不要封装成实体类了,应该是要)

    第二章:SpringMVC实现文件上传

    1. 文件上传的回顾

    (?web学过吗?只记得文件下载webday15学过,文件上传没有丝毫印象。。。

    新建模块springmvc_day02_02_fileupload

    普通超链接a和herf指向controller的方法执行(啊啊啊也可以带参数比如day01里面很多超链接传参注解,比如

    <a href="anno/testRequestParam?myname=哈哈">RequestParam</a>

    。。。表单是带着请求参数指向方法

    “/”开头代表根目录 一般herf里面不是,但reqmapping是带/的

      1. 编写文件上传的JSP页面

        A :form 表单的 enctype 取值必须是:multipart/form-data     (可以切割请求体)

              默认值是:application/x-www-form-urlencoded)     enctype:是表单请求正文的类型

        B :method 属性取值必须是 Post

        C :提供一个文件选择域<input type=”file” /> 

    index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>文件上传</h3>
    
        <form action="/user/fileupload1" method="post" enctype="multipart/form-data">
            选择文件:<input type="file" name="upload"/><br>
            <input type="submit" value="上传">
            <%--现在点文件 点上传 就会跳到controller里面的上传方法--%>
        </form>
    
    </body>
    </html>

    这个编完点选择文件后面的input框是真的可以上传文件!神奇!(有点熟悉了。。好像web里是经历过这个,学前端的时候好像。。。

    点上传的话就会执行controller里面的方法的业务!所以接下来是在controller里面写在服务器端接收文件的业务逻辑!

      2. 导入文件上传的jar包(commons-fileupload)

        <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>
    View Code

      3. 编写文件上传的Controller控制器

    表单都封装在request里面,拿的话用request对象

        /**
         * 文件上传
         * @return
         */
        @RequestMapping("/fileupload1")
        public String fileUpload1(HttpServletRequest request) throws Exception {
            System.out.println("文件上传。。。");
            //使用fileuploa组件完成文件上传
            //上传的位置:uploads的根目录
            String path = request.getSession().getServletContext().getRealPath("/uploads/");//  request.getServletContext();竟然报红。。。非得加个getSession才行,与web学的不一样。。。
            System.out.println(path);
            //判断该路径是否存在
            File file = new File(path);
            if(!file.exists()){
                //创建该文件夹
                file.mkdirs();
            }
            //解析request对象,获取上传的文件项
            DiskFileItemFactory factory = new DiskFileItemFactory();//组件里的磁盘文件项工厂
            ServletFileUpload upload = new ServletFileUpload(factory);//组件里的上传
            //解析request
            List<FileItem> fileItems = upload.parseRequest(request);
            //遍历快捷键:iter
            for (FileItem fileItem : fileItems) {
                //进行判断当前fileitem对象是否是上传文件项
                if(fileItem.isFormField()){
                    //说明是普通表单项
    
                }else {//说明是上传文件项
                    //获取到上传文件的名称
                    String fileItemName = fileItem.getName();
                    // 把文件的名称设置唯一值,uuid
                    String uuid = UUID.randomUUID().toString().replace("-", "");
                    fileItemName = uuid+"_"+fileItemName;
    
                    //完成文件上传
                    fileItem.write(new File(path,fileItemName));
                    //删除临时文件
                    fileItem.delete();
                }
            }
    
            return "success";
        }
    View Code

    500的错误。。。

    Type Exception Report

    Message Request processing failed; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. D:LenovoQMDownload omcatapache-tomcat-8.5.31 empupload_940f5a15_ae3c_41f5_81e6_46473baa7c39_00000007.tmp (拒绝访问。)

    Description The server encountered an unexpected condition that prevented it from fulfilling the request.

    ---------------------------------------------------------------------------------

    经过我的不懈试验发现,这个是10kb以下大小可以成功保存,超过10kb就报该错误。不知该怎么办。。。。狗生艰难。。。

    (没事,后面的可以10M都ok!!!不要用这个传统方法传文件了,用MVC框架的方法吧!!

    卧槽卧槽卧槽我又试了一下传统方法莫名其妙又可以了。。。迷惑服务器行为。。。。。。。。。但是根本找不到文件。。。耍我。。。ok放弃这个吧)

    2. SpringMVC传统方式文件上传

     文件解析器替代了前边使用jar包得到List然后遍历判断等等的工作。

      1. SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同

      2. 代码如下

        /**
         * springMVC文件上传
         * @return
         */
        @RequestMapping("/fileupload2")
        public String fileUpload2(HttpServletRequest request, MultipartFile upload) throws Exception {
            System.out.println("文件上传2。。。");
            //使用fileuploa组件完成文件上传
            //上传的位置:uploads的根目录
            String path = request.getSession().getServletContext().getRealPath("/uploads/");
    // request.getServletContext();竟然报红。。。非得加个getSession才行,与web学的不一样。。。 System.out.println(path); //判断该路径是否存在 File file = new File(path); if(!file.exists()){ //创建该文件夹 file.mkdirs(); } //说明是上传文件项 //获取到上传文件的名称 String fileItemName = upload.getOriginalFilename(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); fileItemName = uuid+"_"+fileItemName; //完成文件上传 upload.transferTo(new File(path,fileItemName)); return "success"; }

      3. 配置文件解析器对象

        <!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="10485760"/>
        </bean>

    成功上传!!!!

    3. SpringMVC跨服务器方式文件上传

    实际开发中有很多负责不同模块的服务器们

      1. 搭建图片服务器

        1). 根据文档配置tomcat9的服务器,现在是2个服务器,springmvc和fileupload

        2). 导入资料中day02_springmvc5_02image项目,作为图片服务器使用

      2. 实现SpringMVC跨服务器方式文件上传

        1). 导入开发需要的jar包

        <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-core</artifactId>
          <version>1.18.1</version>
        </dependency>
    
        <dependency>
          <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
          <version>1.18.1</version>
        </dependency>
    pom.xml

        2). 编写文件上传的JSP页面

          和之前一样的一组表单

      3. 编写控制器

    /**
         * 跨服务器文件上传 往别的服务器传
         * @return
         */
        @RequestMapping("/fileupload3")
        public String fileUpload3(HttpServletRequest request, MultipartFile upload) throws Exception {
            System.out.println("文件上传3。。。");
            //定义上传服务器的路径
            String path = "http://localhost:8090/uploads/";
    
            //说明是上传文件项
            //获取到上传文件的名称
            String fileItemName = upload.getOriginalFilename();
            // 把文件的名称设置唯一值,uuid
            String uuid = UUID.randomUUID().toString().replace("-", "");
            fileItemName = uuid+"_"+fileItemName;
    
           //实现往别的服务器传 需要导入jersey的两个jar包
            //创建客户端对象
            Client client = Client.create();
    
            //和图片服务器进行连接(我用的01response模块)
            WebResource webResource = client.resource(path + fileItemName);
    
            //上传文件
            webResource.put(upload.getBytes());
            return "success";
        }
    View Code

    失败了呵呵呵呵呵呵呵呵呵呵。。。

    HTTP Status 500 – Internal Server Error


    Type Exception Report

    Message Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8090/uploads/7b154a5ab31b49db953c8173f690c43b_lessthan10kb.txt returned a response status of 404 Not Found

    Description The server encountered an unexpected condition that prevented it from fulfilling the request.

    有缘再解决吧 

    第三章:SpringMVC的异常处理

    系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

    1. 异常处理思路

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

    新建模块springmvc_day02_03_exception

    如果不写异常处理器则直接500,404之类的,很不友好

    2. SpringMVC的异常处理

      1. 自定义异常类

    /**
     * 自定义异常类
     */
    public class SysException extends Exception{//继承异常类
    
        // 存储提示信息的
        private String message;
    
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
    
        public SysException(String message) {//构造方法 则new异常类时必须传提示信息
            this.message = message;
        }
    }

      2. 自定义异常处理器

    /**
     * 异常处理器
     */
    public class SysExceptionResolver implements HandlerExceptionResolver{
    
        /**
         * 处理异常业务逻辑
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @return
         */
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            // 获取到异常对象
            SysException e = null;
            if(ex instanceof SysException){
                e = (SysException)ex;
            }else{
                e = new SysException("系统正在维护....");
            }
            // 创建ModelAndView对象
            ModelAndView mv = new ModelAndView();
            mv.addObject("errorMsg",e.getMessage());//异常信息键值对存到req域里
            mv.setViewName("error");//跳到error.jsp 可以用el显示上面存的
            return mv;
        }
    
    }
    View Code

      3. 配置异常处理器

        <!--配置异常处理器-->
        <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>

    实现思路:

    1.自定义一个异常处理器实现HandlerExceptionResolver接口,跳转至指定的error,jsp

    2.写一个error.jsp,打印异常处理器给出的异常原因

    2.写一个异常类,继承Exception类,给一个message属性以及它的getters&setters,构造方法。

    3.在Usercontroller类中模拟异常,在catch中throw new 异常处理器对象

    4.在springmvc.xml中写一个bean,配置异常处理器。

    第四章:SpringMVC框架中的拦截器

    1. 拦截器的概述

      1. SpringMVC框架中的拦截器用于对处理器Controller进行预处理和后处理的技术。山贼(类似过滤器,过滤器拦截后台的资源)

      2. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。

      3. 拦截器和过滤器的功能比较类似,有区别

        1). 过滤器是Servlet规范的一部分,任何框架和java web工程都可以使用过滤器技术。(sun公司的)

        2). 拦截器是SpringMVC框架独有的

        3). 过滤器配置了/*,可以拦截任何资源

        4). 拦截器只会对控制器中的方法进行拦截。(不拦资源)

      4. 拦截器也是AOP思想的一种实现方式

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

    2. 自定义拦截器步骤

    新建springmvc_day02_04_interceptor模块

      1. 创建类,实现HandlerInterceptor接口,重写需要的方法

    /**
     * 自定义拦截类
     */
    public class Myinterceptor1 implements HandlerInterceptor {
        /**
         * 预处理,controller方法执行前,进行拦截的方法
         * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
         * return false不放行
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
        * 可以使用转发或者重定向直接跳转到指定的页面。 
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("MyInterceptor1执行了。。。");
            return true;
        }
    }

      2. 在springmvc.xml中配置拦截器类

        <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--你要拦截的具体方法-->
                <mvc:mapping path="/user/*"/>
                <!--你不要拦截的方法-->
                <!--<mvc:exclude-mapping path=""-->
                <!--配置拦截器对象-->
                <bean class = "com.xxw.interceptor.Myinterceptor1"/>
            </mvc:interceptor>
        </mvc:interceptors>

    3. HandlerInterceptor接口中的方法

      1. preHandle方法是controller方法执行前拦截的方法(预处理)

        1). 可以使用request或者response跳转到指定的页面

        2). return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。

        3). return false不放行,不会执行controller中的方法。(写个跳转直接跳页面了,就req.getDispater.forward转发走了

      2. postHandlecontroller方法执行后执行的方法,在JSP视图执行前。(后处理)

        1. 可以使用request或者response跳转到指定的页面

        2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示

      3. postHandle方法是在JSP执行后执行

        1. request或者response不能再跳转页面了

      4.afterCompletion方法 jsp页面执行后,该方法最终执行

        /**
         * success.jsp页面执行后,该方法会执行
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("MyInterceptor1执行了...最后1111");
        }

      4. 配置多个拦截器

      1. 再编写一个拦截器的类

    Myinterceptor2.java

      2. 配置2个拦截器

    再写一个 <mvc:interceptor> 标签内配置

  • 相关阅读:
    linux vsftpd
    java运用FFMPEG视频转码技术
    使用ffmpeg实现转码样例(代码实现)
    最简单的基于FFMPEG的转码程序
    关于Android Studio升级到2.0后和Gradle插件不兼容的问题
    Android设计模式之命令模式、策略模式、模板方法模式
    Android设计模式源码解析之桥接模式
    Android 项目利用 Android Studio 和 Gradle 打包多版本APK
    RTMP协议详解(转)
    Android 如何使用juv-rtmp-client.jar向Red5服务器发布实时视频数据
  • 原文地址:https://www.cnblogs.com/gezi1007/p/12892499.html
Copyright © 2020-2023  润新知