Spring学习_day3

Spring整合Web开发

  • 首先我们需要将环境搭好,因为需要是Spring + web,对应的步骤是:

File -> Project Structure -> Modules -> 点击+,new Module -> 选择maven,并勾选右边的Create from archetype,然后再点击下面的maven-archetype-webapp即可 -> next ,之后就来到了这一步
在这里插入图片描述

然后Name,Location,GroupId根据自己的需要进行修改,再次点击next,之后直接点击finish即可.

  • 导入相应的依赖

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    
  • webapp/WEB-INF目录下创建Spring的核心配置文件applicationContext.xml,当然也可以放在resources目录下面

    <?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:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="day5.demo"></context:component-scan>
    
    </beans>
    
  • 创建UserDao,UserService接口,并且创建他们的实现子类UserDaoImpl,UserServiceImpl

    public interface UserDao {
        public void save();
    }
    
    @Repository("userDao") //相当于<bean id="userDao" class="xxxx"></bean>
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("UserDao is saving.....");
        }
    }
    
    public interface UserService {
        public void save();
    }
    
    @Service("userService")
    public class UserServiceImpl implements UserService {
        @Autowired
        @Qualifier("userDao")
        private UserDao userDao;
        @Override
        public void save() {
            userDao.save();
        }
    }
    
    
  • 创建UserServlet类进行测试

    public class UserServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ApplicationContext application = new AnnotationConfigApplicationContext(SpringMVCConfiguration.class);
            UserService userService = application.getBean("userService", UserService.class);
            userService.save(); //输出UserDao is saving....
        }
    }
    
    

    同时我们需要在web.xml中配置对应的Servlet:

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
        <servlet>
         <servlet-name>UserServlet</servlet-name>
         <servlet-class>day5.demo.web.servlets.UserServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>UserServlet</servlet-name>
        <url-pattern>/UserServlet</url-pattern>
      </servlet-mapping>
    </web-app>
    
    

但是这时候我们如果有多个Servlet,那么每次都需要写下面2步:

ApplicationContext application = new AnnotationConfigApplicationContext(SpringMVCConfiguration.class);
UserService userService = application.getBean("userService", UserService.class);

所以为了每次调用方法的时候,不需要执行这2步,Spring就考虑在tomcat服务器启动的时候,将application这个对象保存到ServletContext域中,然后如果需要获取ApplicationContext对象的时候,就可以从ServletContext中调用getAttribute(“xxx”)方法获得

而要想tomcat服务器启动的时候,将application对象保存到ServletContext,那么就需要利用ContextLoaderListener监听器来实现,一旦tomcat服务器启动,那么就会触发它的初始化方法,这时候我们就要在这个方法中将application保存到ServletContext域中即可。

而我们创建application对象的时候,还需要知道核心配置文件的名字。那么这时候我们可以通过在web.xml中通过<context-param></context-param>来定义全局初始化变量

但是可能会由于ServletContext调用getAttribute(“xxx”)获取ApplicationContext对象的时候,xxx值会忘记,所以我们可以交给WebApplicationContextUtils调用getWebApplicationContext(ServletContext)来获得application对象。而要利用WebApplicationContextUtils,则需要导入依赖spring-web,但是由于我们已经导入了spring-webmvc,所以不用在导入依赖spring-web了.

所以这时候web.xml的代码修改成为了:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <context-param>
      <!--全局初始化变量:Spring核心配置文件-->
      <param-name>applicationContext</param-name> <!--可以任意写-->
      <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <listener>
      <!--
      添加监听器ContextLoaderListener,这样就会在web启动/销毁的时候,
      就会触发监听事件
      -->
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
    <servlet>
     <servlet-name>UserServlet</servlet-name>
     <servlet-class>day5.demo.web.servlets.UserServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/UserServlet</url-pattern>
  </servlet-mapping>
</web-app>

对应的UserServlet代码为:

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        ApplicationContext application = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        UserService userService = application.getBean("userService", UserService.class);
        userService.save();
    }
}

Spring MVC快速入门

首先要入门Spring MVC,需要先搭建好它的环境,而他的环境搭建和Spring整合Web的环境搭建步骤一样。当环境搭建好之后,就可以快速入门了,测试案例的基本步骤为:

  • 导入spring-mvc的依赖,但是由于上面搭建环境中已经导入了spring-webmvc依赖,所以这一步可以不用进行了
  • 配置spring的前端控制器DispatcherServlet,和配置其他的Servlet一样是在web.xml中进行配置
  • 创建controller,并且将controller添加到Spring容器中。因为是在controller层,所以这时候我们既可以使用注解@Component,也可以使用@Controller注解,从而将对应的controller类添加到Spring容器中
  • 利用注解@RequestMapping或者@GetMapping或者@PostMapping,根据url,映射到某一个controller类中的某一个方法.例如@RequestMapping(“/quick”),如果url为localhost:8080/quick,那么就会映射到这个注解作用的方法中
  • 要执行对应的controller类,那么我们需要扫描组件。所以我们需要创建spring-mvc.xml这个配置文件,然后在这个配置文件中利用context命名空间,来进行组件扫描

对应的UserController代码为:

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/quick") //当请求的参数试quick的时候,那么就会执行这个方法
    //如果再类的上面也是用@RequestMapping,那么url是/user/quick的时候,才会映射到当前这个类的save方法
    //这时候,返回值就会在/user/success.jsp中寻找这个文件,然后如果没有,就会发生了报错
    //所以需要再success.jsp的前面加上/,表示再当前的路径下面
    public String save(){
        System.out.println("UserController save is running......");
        return "/success.jsp";//前端返回到这个页面
    }
    //@RequestMapping(value="/test1", method= RequestMethod.GET)
    @GetMapping("/test1")
    //method参数表示请求的方法是GET的时候才会和当前的方法映射,否则不会
    //此时就相当于@GetMapping("/test1"),同样的,如果method的值是POST,那么相当于@PostMapping
    public String test1(){
        System.out.println("UserController test is running......");
        return "/success.jsp";

    }
    @GetMapping(value="/test2",params={"username","age"})
    //使用参数params,表示希望请求的url地址中必须要有参数名为username,age
    //否则就会发生报错
    public String test2(){
        System.out.println("UserController test2 is running........");
        return "/success.jsp";
    }
}

对应的spring-mvc.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--
    利用context命名空间,context:component-scan进行组件扫描
    而因为已经有了spring来扫描其他层的组件了,所以需要spring mvc来
    扫描controller层的组件
    -->
    <context:component-scan base-package="day5.demo.controller"></context:component-scan>

    <!--
    视图配置文件,可以配置视图名称的前缀以及后缀
    这样再方法的返回值中就可以不用这样写:/success.jsp
    或者/jsps/success.jsp了(success.jsp文件再jsps目录下面)

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    -->
</beans>

对应的web.xml文件:

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Application</display-name>
    <!--配置Spring MVC的前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</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>
        <!--对于所有的请求,都会经过这个DispatcherServlet-->
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
</web-app>

当我们输入localhost:8080/user/quick1,那么就会来到了success.jsp页面了,执行的是UserController中的save方法:
在这里插入图片描述

Spring MVC的数据响应

Spring MVC页面跳转

在Spring MVC中,如果需要进行页面跳转,主要有2种方式:

  • 直接返回一个字符串,其中这个字符串是表示跳转页面对应的文件,如jsp文件。当然也可以是对应文件的名字,只是这时候我们需要在spring-mvc.xml中配置内部资源解析器,来设置属性prefix,sufix即可.

  • 直接返回一个ModelAndView对象,并且可以调用addObject方法,来添加数据,如果需要在页面中获取这个数据,那么可以通过spring表达式${xx}来获得,调用setViewName(“xxx”),从而跳转到xxx这个页面中

    但是,如果最后发现,利用${yyy}(spring表达式)没有获取到addObject中添加的数据的值,那么是因为在web.xml中下面的一串数据导致的,我们只需要将下面这串数据

    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    

    改成<?xml version="1.0" encoding="UTF-8" ?>即可.

对应的代码为:

@Controller
public class ControllerTest2 {
    @RequestMapping("/quick1")
    public String test1(){
        return "success.jsp"; //直接跳转到success.jsp中
    }
    @RequestMapping("/quick2") //通过ModelAndView进行页面跳转
    public ModelAndView test2(ModelAndView modelAndView){
        //我们不需要向这个方法传递参数,因为Spring会帮我们注入
        //将username添加到页面中,如果需要在页面中显示,可以通过spring表达式显示${username}
        modelAndView.addObject("username","小希");
        //将跳转到哪一个页面中
        modelAndView.setViewName("success2.jsp");
        return modelAndView;
    }
}

success.jsp的代码为:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>spring mvc快速入门</title>
</head>
<body>
    <h1>
        spring mvc的快速入门的基本步骤:<br>
        1、导入spring-mvc依赖.但是如果导入了spring-webmvc,那么可以不用再导入spring-mvc依赖<br>
        2、创建spring的前端控制器DispatcherServlet.即在web.xml中配置即可<br>
        3、创建controller<br>
        4、通过使用注解,来将controller中的方法和请求产生映射@RequestMapping
        或者@GetMapping、@PostMapping<br>
        5、创建spring-mvc的配置文件spring-mvc.xml,进行组件扫描@ComponentScan<br>
        6、做出响应<br>
    </h1>
</body>
</html>

success2.jsp的代码为:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>通过ModelAndView实现页面跳转</title>
</head>
<body>
    <span>
        通过ModelAndView实现页面跳转。并且可以通过ModelAndView调用addObject<br>
        方法来封装数据。然后在页面中通过spring表达式${xxx}来获得.
    </span>
    <span>你好呀! </span>
    <h1>${username}</h1> <!--Spring表达式,来获取username的值-->
</body>
</html>

如果url是localhost:8080/quick1,那么前端界面是success.jsp的内容:
在这里插入图片描述

如果url是localhost:8080/quick2,那么前端界面success2.jsp的内容:
在这里插入图片描述

而通过返回ModelAndView对象进行页面跳转还有其他的形式,我们可以直接通过new ModelAndView()来创建ModelAndView对象,而上面中则是通过Spring MVC注入的。也可以返回一个字符串,但是通过参数Model调用addAttribute来添加数据。所以对应的代码是:

@RequestMapping("/quick3")
//通过返回ModelAndView对象实现页面跳转,然后调用addObject来添加数据,调用setViewName来设置跳转的页面
public ModelAndView test3(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("username","大大怪");
    modelAndView.setViewName("success2.jsp");
    return modelAndView;
}
@RequestMapping("/quick4")
//通过返回字符串来实现页面跳转,但是它可以通过Model调用addAttribute来添加数据到页面中
public String test4(Model model){
    //通过Model来封装数据,然后返回字符串,跳转到对应的页面中
    //此时model时调用addAttribute来添加数据的
    model.addAttribute("username","小小怪");
    return "success2.jsp";
}

当输入localhost:8080/quick3,运行结果为:
在这里插入图片描述

输入localhost:8080/quick4,运行结果为:
在这里插入图片描述

Spring MVC回写数据

Spring MVC回写数据,主要是回写字符串,或者一个集合或者数组。

如果需要回写的是一个字符串,主要有2种方式:

  • 我们在web开发中是通过response调用getWriter获取对应的Writer对象,然后再调用对应的方法进行响应,例如response.getWriter().println("xxxxx"),那么我们就可以会写了xxxx字符串了。但是显然我们上面的controller中的方法中没有HttpServletResponse对象,所以我们可以像上面的ModelAndView那样,通过Spring MVC来注入HtttpServlertResponse,然后就可以执行response.getWriter().println("xxxxx")代码进行回写数据了。此时,方法没有返回值,所以应该是void.这时候如果响应的数据中含有中文,那么就可能会出现乱码问题。所以这时候和web开发解决响应乱码的方法是一样的的,可以通过response调用setContextType(“text/html;charset=utf-8”)来解决.

  • 我们可以直接返回字符串,但是这时候会被Spring MVC认为是需要进行页面跳转,然后可能就会发生报错,因为这个字符串对应的页面并没有存在。所以为了告诉给Spring MVC知道,这个字符串是用于回写数据的,那么我们就需要再方法的上方使用注解@ResponseBody,这样Spring MVC就知道这个字符串适用于回写数据的.

    但是值得注意的是,@ResponseBody来回写数据的时候,需要注意编码的问题,如果返回的是一个对象,那么使用的UTF-8编码,但是如果是String类型,那么Spirng中默认的是ISO-8859编码,所以我们需要在注解@RequestMapping中设置produces的值为text/html;charset=utf-8,也即@RequestMapping(value=“/xxx”,produces={“text/html;charset=utf-8”})即可解决回写数据为String的时候,使用@ResponseBody中文乱码的问题.其中produces的值还有"application/json;charset=utf-8",同样可以解决乱码的问题,但是返回的字符串将是json格式

对应的代码为:

@RequestMapping("/quick5")
public void test5(HttpServletResponse response) throws IOException {
    //此时因为考虑到响应的编码问题,所以需要通过response
    // 调用setContentType("text/html;charset=utf-8")来解决响应中文乱码问题
    response.setContentType("text/html;charset=utf-8");
    response.getWriter().println("通过response调用getWriter().println()来进行回写数据的");
}
@RequestMapping(value="/quick6",produces={"text/html;charset=utf-8"})
@ResponseBody
public String test6(){
    return "通过使用@ResponseBody,告诉Spring MVC,这个字符串用于回写数据的";
}

当在搜索栏输入localhost:8080/quick5时,运行结果为:
在这里插入图片描述

在搜索栏输入localhost:8080/quick6时,运行结果为:
在这里插入图片描述

如果我们希望将对象或者集合变成json格式的字符串回写,那么我们可以直接返回这个对象,此时交给Spring MVC自动将对象转成json格式的字符串,我们也可以手动的将对象转成对应的json格式的字符串来回写数据

  • 手动将对象或者集合转成json格式的字符串

    要通过手动将对象或者集合转成json格式的字符串,那么我们需要导入相应的依赖:jackson-core,jackson-databind,jackson-annotations

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

    然后我们创建ObjectMapper对象,通过objectMapper对象调用writeValueAsString(”xxxx"),就可以将xxxx对象转成json格式的字符串,然后我们就可以利用@ResponseBody注解,来回写数据了。同样的,考虑到中文编码的问题,我们需要设置@RequestMapping中的属性produces的值为text/html;charset=utf-8解决乱码问题

    对应的代码为:

    @RequestMapping(value="/quick7",produces={"text/html;charset=utf-8"})
    @ResponseBody //告诉Spring mvc框架,返回的字符串适用于回写的,不是用于页面跳转
    public String test7() throws JsonProcessingException {
        User user = new User();
        user.setName("小王");
        user.setAge(19);
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(user);
        return json;
    }
    @RequestMapping(value="/quick8",produces={"text/html;charset=utf-8"})
    @ResponseBody
    public String test8() throws JsonProcessingException {
        List<User> lists = new ArrayList<>();
        User user1 = new User();
        user1.setName("小李");
        user1.setAge(19);
        User user2 = new User();
        user2.setName("小孟");
        user2.setAge(20);
        lists.add(user1);
        lists.add(user2);
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(lists);
        return json;
    }
    

    当搜索栏输入localhost:8080/quick7时,测试结果:
    在这里插入图片描述

    输入的是localhost:8080/quick8时,测试结果为:
    在这里插入图片描述

    如果这时候我们@RequestMapping的属性produces的值为application/json;charset=utf-8,那么原本就已经是json格式的字符串,就会变成了下面的字符串:
    在这里插入图片描述
    在这里插入图片描述
    此时,为了将它的格式变成上面的格式,那么我们需要在spring-mvc.xml中配置处理器适配器,让它的messageConverter的元素含有StringHttpMessageConverter。

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
            </list>
        </property>
    </bean>
    

    此时输出结果就可以恢复到和@RequestMapping(produce=“text/html;charset=utf-8”)一样的结果了。

  • 利用Spring MVC自动将对象或者集合转成json格式的字符串

    如果我们希望直接返回的是一个对象或者集合,然后由Spring MVC来将对象或者集合自动转成json格式的字符串,那么我们同样是在spring-mvc.xml中配置处理器适配器,让他的属性messageConverter中的元素含有MappingJackson2HttpMessageConverter,这样就会将对象转成json格式的字符串了,对应的代码为:

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
            </list>
        </property>
    </bean>
    

    这样我们直接返回对象或者集合的时候,会将自动将对象变成json格式的字符串,但是由于返回的是字符串,默认是进行页面跳转,所以依旧需要使用注解@ResponseBody,告诉Spring MVC转成的字符串是用来回写数据的,代码如下所示:

    @RequestMapping(value="/quick9",produces={"text/html;charset=utf-8"})
    @ResponseBody
    public User test9(){
        User user = new User();
        user.setName("小王");
        user.setAge(19);
        return user;
    }
    @RequestMapping(value="/quick10",produces={"text/html;charset=utf-8"})
    @ResponseBody
    public List<User> test10(){
        List<User> lists = new ArrayList<>();
        User user1 = new User();
        user1.setName("小李");
        user1.setAge(19);
        User user2 = new User();
        user2.setName("小孟");
        user2.setAge(20);
        lists.add(user1);
        lists.add(user2);
        return lists;
    }
    

    然后输入localhost:8080/quick9还是输入localhost:8080/quick10,运行结果都是下面的样子,提示No converter for [class day5.demo.domain.User] with preset Content-Type 'null'在这里插入图片描述

    这时候我们需要将@RequestMapping中的属性produces的值改为application/json;charset=utf-8即可解决问题,不可以是produces={"text/html;charset=utf-8","application/json;charset=utf-8"},否则还是会发生报错.修改之后的运行结果如下所示:
    在这里插入图片描述
    在这里插入图片描述

    而我们配置处理器适配器,都需要在spring-mvc.xml中写一大串的代码,所以为了解决这个问题,我们可以使用mvc注解驱动<mvc:annotation-driven/>,同样需要使用到了mvc命名空间,而使用mvc命名空间和使用context命名空间一样.所以对应的spring-mvc.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.xsd
                            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="day5.demo.controller"></context:component-scan>
        <!--
            使用mvc命名空间,需要加入xmlns:mvc="http://www.springframework.org/schema/mvc"这一串
            同时xsi:schemaLocation中同时添加http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
         -->
        <mvc:annotation-driven/>
    
    </beans>
    

    这样就可以实现和上面配置处理器适配器的代码是一样的效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值