SpringMVC简单入门——课件转载

体验springmvc

目前比较好的MVC框架,老牌的有Struts1.x、Webwork (Struts2)。新的MVC框架有Spring MVC、Tapestry、JSF等。这些大多是著名团队的作品。这些框架都提供了较好的层次分隔能力。在实现良好的MVC 分隔的基础上,通过提供一些现成的辅助类库,同时也促进了生产效率的提高。

Spring MVC工作原理

  • Dispatcher Servlet分发器
  • Handler Mapping 处理器映射
  • Controller 控制器
  • ModelAndView
  • ViewResolver 视图解析器 

Java MVC 框架性能测试

  • 测试结果: 

Spring-framework

Spring框架是业务层框架,核心组件是容器 它是管理bean的,广义上讲任何一个javaBean它都管理,实例化对象 两大概念:IOC、AOP

IOC : (Inversion of Control)

       它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。它是获得依赖对象的方式。

好莱坞原则,即“不要打电话过来,我们会打给你”。


AOP:( Aspect-Oriented Programming) 面向方面编程

       可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。
      当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

SpringMVC

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。 

面试要点:Struts1、Struts2和springmvc比较

  • 都是web层框架。
  • Struts1是基于servlet;Struts2是基于filter;springmvc是基于servlet 。
  • Struts1的action是单例模式,线程不安全的;Struts2 action是原型模式 prototype,每次访问对象都会创建新的实例,保证线程安全性;springmvc controller是单例模式,整个程序只有一个对象实例。Spring的安全性是通过绑定threadlocal实现。
  • Struts1使用JSTL EL表达式,但是对集合和索引属性的支持很弱。Struts2采用 OGNL。
  • struts2是类级别的拦截, 一个类对应一个request上下文,springmvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应。
  • Strust1中通常以action访问时.do,struts2、spring mvc 都是以.action做结尾。
  • spring3 mvc可以认为已经100%零配置了。

开发步骤:

  1. 新建web project
  2. 引入jar包

    spring-aop-3.2.2.jar 面向切片编程
    spring-aspects-3.2.2.jar 提供对AspectJ的支持,以便可以方便的将面向方面的功能集成进IDE中
    spring-beans-3.2.2.jar 核心。访问配置文件、创建和管理bean 以及进行IoC/DI操作相关的所有类。
    spring-context-3.2.2.jar为Spring 核心提供了大量扩展。
    spring-context-support-3.2.2.jar
    spring-core-3.2.2.jar Spring 框架基本的核心工具类。外部依赖Commons Logging 。
    spring-expression-3.2.2.jar 配置对象的注入,它便是SpEL (Spring Expression Language)
    spring-web-3.2.2.jar Web 应用开发时,用到Spring 框架时所需的核心类
    spring-webmvc-3.2.2.jar  Spring MVC 框架相关的所有类。包括框架的Servlets,Web MVC框架,控制器和视图支持。
              注意spring3.0的包名是 org.spingframework.web.servlet-3.1.0 RELEASE.jar
    
    com.springsource.org.apache.commons.logging-1.1.1.jar 日志
    com.springsource.org.aopalliance-1.0.0.jar  AOP联盟的API包,里面包含了针对面向切面的接口。
    
  3. 配置分发器servlet DispatchServlet

    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
    
  4. 创建控制器类

    public class HomeController extends AbstractController {
    
        protected ModelAndView handleRequestInternal(HttpServletRequest request,
                HttpServletResponse response) throws Exception {
            System.out.println("HomeController...");
    
            return new ModelAndView("index");
        }
    
    }
    
  5. 配置beans,创建spring配置文件 /WEB-INF/action-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans                    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    
        <!-- 控制器 -->                
        <bean name="/home.action" class="cn.albin.springmvc.controller.HomeController"/>
        <!-- 内部资源视图解析器 -->  
        <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsps/"/>    <!-- 前缀 -->
            <property name="suffix" value=".jsp"/>      <!-- 后缀 -->
        </bean>
    
    </beans>    
    
  6. 创建jsp文件

    <%@ page language="java" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>index.jsp</title>
      </head>
    
      <body> 
        This is my JSP page. <br>
      </body>
    </html>
    
  7. 发布、测试

SpringMVC 入门

web.xml 配置

<!-- 注册springmvc核心控制器 -->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 通知DispatcherServlet去指定的目录下加载springmvc.xml配置文件 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>



<!-- 注册spring提供的针对POST请求的中文乱码问题 -->
<filter>
    <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

springmvc.xml配置文件(src 目录)

视图解析器【解析视图逻辑名对应的真实路径】【配置可省】InternalResourceViewResolver

<?xml version="1.0" encoding="UTF-8"?>
<beans 
      xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:mvc="http://www.springframework.org/schema/mvc"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
      ">

      <!-- 注册Action(必须配置) -->
      <bean name="/hello.action" class="cn.albin.javaee.springmvc.app07.HelloAction"></bean>

      <!-- 
        如果Action中书写的是视图逻辑名称,那么视图解析器就必须配置 
        如果Action中书写的是视图真实名称,那么视图解析器就可选配置 
      -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 路径前缀 -->
            <property name="prefix" value="/jsp/"/>
            <!-- 路径后缀 -->
            <property name="suffix" value=".jsp"/>
            <!-- 前缀+视图逻辑名+后缀=真实路径 -->
      </bean>
</beans>  

控制层

/**
 * 单例
 * 控制器Action
 * 处理器Action
 * @author albin
 */
public class HelloAction implements Controller{
    /**
     * 业务方法
     */
    public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message","这是我的第二个springmvc应用程序,视图使用逻辑名");

        //原来封装视图的真实路径
        //modelAndView.setViewName("/jsp/success.jsp");

        //现在封装视图的逻辑名称
        modelAndView.setViewName("success");

        return modelAndView;
    }
}

初识原理

映射器Mapping【什么样的请求交给Action】【配置可省】BeanNameUrlHandlerMapping

  • java

    /**
     * 控制器
     * @author 谢斌
     */
    public class UserAction implements Controller{
        public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {
            System.out.println("操作用户");
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("message","操作用户成功");
            modelAndView.setViewName("success");
            return modelAndView;
        }
    }
    
  • xml

      <!-- 注册Action -->
      <bean name="/add.action" class="cn.albin.javaee.springmvc.app08.UserAction"></bean>
    
      <!-- 映射器 -->
      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
    
    
      <!-- 适配器 -->
    
    
      <!-- 视图解析器 -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/jsp/"/>
            <property name="suffix" value=".jsp"/>
      </bean>   
    

映射器SimpleUrlHandlerMapping适合】于将多个请求,映射到同一个Action

  <!-- 注册Action -->
  <bean id="userActionID" class="cn.albin.javaee.springmvc.app08.UserAction"></bean>


  <!-- 注册映射器
       【适合】于将多个请求,映射到同一个Action
   -->
  <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <!-- key表示请求路径 -->
                <prop key="/update.action">userActionID</prop>
                <prop key="/delete.action">userActionID</prop>
                <prop key="/find.action">userActionID</prop>
            </props>
        </property>
  </bean>

适配器Adapter【Action实现什么接口】【配置可省】SimpleControllerHandlerAdapter

  • java

    /**
     * 控制器是实现Controller接口的类
     * @author 谢斌
     */
    public class EmpAction implements Controller{
        public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {
            ModelAndView  modelAndView = new ModelAndView();
            //设置编码方式
            request.setCharacterEncoding("UTF-8");
            //获取员工姓名
            String username = request.getParameter("username");
            //显示
            System.out.println("员工姓名:" + username);
            //将员工姓名封装到ModelAndView对象中去
            modelAndView.addObject("message",username);
            //将真实路径名封装到ModelAndView对象中去
            modelAndView.setViewName("/jsp/success.jsp");
            return modelAndView;
        }
    }
    
  • xml

    <!-- EmpAction处理类 -->
    <bean name="/add.action" class="cn.albin.javaee.springmvc.app09.EmpAction"></bean>  
    
    <!-- 映射器(省) --> 
    
    <!-- 适配器 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
    
    <!-- 视图解析器(省) -->  
    

注解快速入门

  • java

    /**
     * 单例
     * 控制器(程序员)
     */
    @Controller
    public class HelloAction{
        public HelloAction(){
            System.out.println("HelloAction()::" + this.hashCode());
        }
        /**
         * 业务方法
         * 只要是/hello.action的请求,都交由HelloAction对象中的hello()方法去处理
         */
        @RequestMapping(value="/hello.action")   
        public String hello(Model model) throws Exception{
            System.out.println("HelloAction::hello()");
            model.addAttribute("message","你好");
            return "success";
        }
        /**
         * 业务方法
         * 只要是/bye.action的请求,都交由HelloAction对象中的bye()方法去处理
         */
        @RequestMapping(value="/bye.action")   
        public String bye(Model model) throws Exception{
            System.out.println("HelloAction::hello()");
            model.addAttribute("message","再见");
            return "success";
        }
    }
    
  • xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans 
          xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:context="http://www.springframework.org/schema/context"
          xsi:schemaLocation="
          http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/mvc
          http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd        
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          ">    
        <!-- Action,让springioc容器去扫描带@Controller的类 -->
        <context:component-scan base-package="cn.albin.javaee.springmvc.app14"/>
        <!-- 视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans> 
    

一个Action中,写多个类似的业务控制方法

  • 控制器

    /**
     *  控制器
     * @author albin
     */
    @Controller
    @RequestMapping(value="/user")
    public class UserAction {
        /**
         * 用户注册
         */
        @RequestMapping(value="/register")
        public String registerMethod(Model model) throws Exception{
            model.addAttribute("message","员工注册成功");
            return "/jsp/success.jsp";
        }
        /**
         * 用户登录
         */
        @RequestMapping(value="/login")
        public String loginMethod(Model model) throws Exception{
            model.addAttribute("message","员工登录成功");
            return "/jsp/success.jsp";
        }
    
  • spring.xml

    <!-- Action,让springioc容器去扫描带@Controller的类 -->
    <context:component-scan base-package="cn.albin.javaee.springmvc.app15"/>
    <!-- 映射器(省) -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    </bean>
    

在业务控制方法中写入普通变量收集参数

限定某个业务控制方法,只允许GET或POST请求方式访问

  • 控制器

    /**
     *  控制器
     * @author albin
     */
    @Controller
    @RequestMapping(value="/user")
    public class UserAction {
        /**
         * 用户注册,只能接收POST请求
         */
        @RequestMapping(method=RequestMethod.POST,value="/register")
        public String registerMethod(Model model,String username,String salary) throws Exception{
            System.out.println("用户注册-->" + username + ":" + salary);
            model.addAttribute("message","员工注册成功");
            return "/jsp/success.jsp";
        }
        /**
         * 用户登录,即能接收POST请求,又能接收GET请求
         */
        @RequestMapping(value="/login")
        public String loginMethod(Model model,String username) throws Exception{
    
            System.out.println("用户登录-->" + username);
            model.addAttribute("message","员工登录成功");
            return "/jsp/success.jsp";
        }
    }
    

在业务控制方法中写入HttpServletRequest,HttpServletResponse,Model等传统web参数

  • 控制器

    /**
     *  控制器
     * @author albin
     */
    @Controller
    @RequestMapping(value="/user")
    public class UserAction {
        /**
         * 用户注册,只能接收POST请求
         */
        @RequestMapping(method=RequestMethod.POST,value="/register")
        public String registerMethod(HttpServletRequest request,HttpServletResponse response) throws Exception{
    
            //获取用户名和薪水
            String username = request.getParameter("username");
            String salary = request.getParameter("salary");
            System.out.println("用户注册-->" + username + ":" + salary);
    
            //绑定到session域对象中
            request.getSession().setAttribute("username",username);
            request.getSession().setAttribute("salary",salary);
    
            //重定向/jsp/success.jsp页面
            //response.sendRedirect(request.getContextPath()+"/jsp/success.jsp");
    
            //转发/jsp/ok.jsp页面
            request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
    
            //转发(提倡)
            return "/jsp/success.jsp";
        }
    }
    

在业务控制方法中写入模型变量收集参数,且使用@InitBind来解决字符串转日期类型

  • 控制器

    /**
     *  控制器
     * @author albin
     */
    @Controller
    @RequestMapping(value="/user")
    public class UserAction {
        /**
         * 自定义类型转换器
         */
        @InitBinder
        public void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {
            binder.registerCustomEditor(
                    Date.class, 
                    new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),true));
        }
        /**
         * 用户注册,只能接收POST请求
         */
        @RequestMapping(method=RequestMethod.POST,value="/register")
        public String registerMethod(User user,Model model) throws Exception{
            System.out.println("用户注册:" + user.toString());
            //将user绑定到model对象中
            model.addAttribute("user",user);
            //转发到success.jsp页面
            return "/jsp/success.jsp";
        }
    }
    

在业务控制方法中写入User,Admin多个模型收集参数

  • 控制器

    /**
     * 控制器
     * @author albin
     */
    @Controller
    @RequestMapping(value="/person")
    public class PersonAction {
        @InitBinder
        public void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {
            binder.registerCustomEditor(
                    Date.class, 
                    new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
        }
    
    
    
    
    
        /**
         * 业务方法
         */ 
        @RequestMapping(value="/register")
        public String registerMethod(Bean bean,Model model) throws Exception{
            System.out.println("普通用户:" + bean.getUser());
            System.out.println("管理员:" + bean.getAdmin());
            //将user和admin都绑定到Model
            model.addAttribute("user",bean.getUser());
            model.addAttribute("admin",bean.getAdmin());
            //转发
            return "/02_person.jsp";
        }
    }
    

在业务控制方法中收集数组参数

@Controller
@RequestMapping(value="/emp")
public class EmpAction {
    @RequestMapping(value="/deleteAll",method=RequestMethod.POST)
    public String deleteAll(Model model,int[] ids) throws Exception{
        System.out.println("需要删除的员工编号分别是:");
        for(int id : ids){
            System.out.print(id+" ");
        }

        model.addAttribute("message","批量删除员工成功");
        return "/jsp/ok.jsp";
    }
}

在业务控制方法中收集List参数

  • 控制器

    @Controller
    @RequestMapping(value="/emp")
    public class EmpAction {
        /**
         * 批量添加员工
         */
        @RequestMapping(value="/addAll",method=RequestMethod.POST)
        public String addAll(Model model,Bean bean) throws Exception{
            for(Emp emp:bean.getEmpList()){
                System.out.println(emp.getUsername()+":"+emp.getSalary());
            }
            model.addAttribute("message","批量增加员工成功");
            return "/jsp/ok.jsp";
        }
    }
    

结果的转发和重定向

  • 控制器

    @Controller
    @RequestMapping(value="/emp")               
    public class EmpAction {
    
        @RequestMapping(value="/find")
        public String findEmpById(int id,Model model) throws Exception{
            System.out.println("查询"+id+"号员工信息");
    
            //转发到EmpAction的另一个方法中去,即再次发送请求
            return "forward:/emp/update.action";
    
            //重定向到EmpAction的另一个方法中去,即再次发送请求
            //return "redirect:/emp/update.action?id=" + id;
    
        }
    
        @RequestMapping(value="/update")
        public String updateEmpById(int id,Model model) throws Exception{
            System.out.println("更新" + id +"号员工信息");
            model.addAttribute("message","更新员工信息成功");
            return "/jsp/ok.jsp";
        }
    
    }
    

JSON 使用

1)导入jackson-core-asl-1.9.11.jar和jackson-mapper-asl-1.9.11.jar

3)在spring.xml配置文件中编写如下代码:

    <!--  
        1)导入jackson-core-asl-1.9.11.jar和jackson-mapper-asl-1.9.11.jar
        2)在业务方法的返回值和权限之间使用@ResponseBody注解表示返回值对象需要转成JSON文本
        3)在spring.xml配置文件中编写如下代码:
        -->
        <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
            <property name="messageConverters">
                    <list>
                        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
                    </list>
            </property>
        </bean>
  • 案例

    @Controller
    @RequestMapping(value="/emp")
    public class EmpAction {
    
    
        /**
         * @ResponseBody Emp 表示让springmvc将Emp对象转成json文本
         */
        @RequestMapping(value="/bean2json")
        public @ResponseBody Emp bean2json() throws Exception{
            //创建Emp对象
            Emp emp = new Emp();
            emp.setId(1);
            emp.setUsername("哈哈");
            emp.setSalary(7000D);
            emp.setHiredate(new Date());
            return emp;
        }
    
    
        @RequestMapping(value="/listbean2json")
        public @ResponseBody List<Emp> listbean2json() throws Exception{
            //创建List对象
            List<Emp> empList = new ArrayList<Emp>();
            //向List对象中添加三个Emp对象
            empList.add(new Emp(1,"哈哈",7000D,new Date()));
            empList.add(new Emp(2,"呵呵",8000D,new Date()));
            empList.add(new Emp(3,"嘻嘻",9000D,new Date()));
            //返回需要转JSON文本的对象
            return empList;
        }
    
    
        @RequestMapping(value="/map2json")
        public @ResponseBody Map<String,Object> map2json() throws Exception{
            //创建List对象
            List<Emp> empList = new ArrayList<Emp>();
            //向List对象中添加三个Emp对象
            empList.add(new Emp(1,"哈哈",7000D,new Date()));
            empList.add(new Emp(2,"呵呵",8000D,new Date()));
            empList.add(new Emp(3,"嘻嘻",9000D,new Date()));
            //创建Map对象
            Map<String,Object> map = new LinkedHashMap<String,Object>();
            //向Map对象中绑定二个变量
            map.put("total",empList.size());
            map.put("rows",empList);
            //返回需要转JSON文本的对象
            return map;
        }
    
    }
    

* jsp

      <body> 
      <input type="button" value="Emp转JSON"/><p>

       <input type="button" value="List<Emp>转JSON"/><p>

       <input type="button" value="Map<String,Object>转JSON"/><p>



       <!-- Map<String,Object>转JSON -->   
       <script type="text/javascript">
            $(":button:last").click(function(){
                var url = "${pageContext.request.contextPath}/emp/map2json.action";
                var sendData = null;
                $.post(url,sendData,function(backData,textStaut,ajax){
                    alert(ajax.responseText);
                });     
            });
       </script>



       <!-- List<Emp>转JSON -->    
       <script type="text/javascript">
            $(":button:eq(1)").click(function(){
                var url = "${pageContext.request.contextPath}/emp/listbean2json.action";
                var sendData = null;
                $.post(url,sendData,function(backData,textStaut,ajax){
                    alert(ajax.responseText);
                });     
            });
       </script>



       <!-- Emp转JSON -->      
       <script type="text/javascript">
            $(":button:first").click(function(){
                var url = "${pageContext.request.contextPath}/emp/bean2json.action";
                var sendData = null;
                $.post(url,sendData,function(backData,textStaut,ajax){
                    //alert(ajax.responseText);
                    var hiredate = backData.hiredate;
                    var date = new Date(hiredate);
                    alert(date.getFullYear()+"年"+(date.getMonth()+1)+"月"+(date.getDate())+"日");
                });     
            });
       </script>

      </body>

猜你喜欢

转载自blog.csdn.net/qq_39459229/article/details/81255325
今日推荐