Spring MVC总结

总结:

  1. Spring MVC 概念
  2. Spring MVC 架构
  3. Spring MVC 环境设置
  4. Spring MVC 架构:运行流程
  5. 基础
    1. Spring MVC -  Hello World示例
    2. 配置文件
      1. web.xml
      2. springmvc.xml
        1. 视图定位:为了安全,一般将jsp文件放在WEB-INF目录下,放在此目录下的文件不能直接访问,需要由核心处理器进行跳转,才能访问,如http://localhost:8080/ssm/WEB-INF/jsp/login.jsp就不能访问,
          http://localhost:8080/ssm/login.jsp就能直接访问。
          struts2中也是将jsp文件放在WEB-INF目录下。
        2. 配置拦截器
    3. 控制器
      1. 接受表单数据:参数绑定
      2. 客户端跳转
    4. 注解实现
  6. session
  7. 上传文件
  8. 关于静态资源拦截、访问以及拦截的几个符号说明,需要如下注意:
    1. web.xml中/、/*、*.action、*.do的区别
      / 表示拦截所有请求 (包括html,但是不拦截.jsp) 建议使用此种方式 (拦截 html.js.css .png等等静态资源) (需要在web.xml中配置放行才能访问)
      /* 拦截所有请求(包括.jsp,但是不拦截.html) 此种方式不建议使用
      *.do *.action 拦截以.do结尾的请求 (不拦截 jsppngjpg .js .css)
    2. spring mvc为什么不能访问静态资源:因为/拦截所有的请求,但是不拦截jsp,所有可以访问index.jsp,而不能访问index.html
      <!-- 配置springmvc的servlet的时候,使用的路径是"/",导致静态资源在默认情况下不能访问,如果想要访问,所以要加上这一段,允许访问jpg。 并且必须加在springmvc的servlet之前,如下-->
    3. 怎么访问静态资源
      可以在servelt中配置放行的静态资源,也可以在springmvc-servlet.xml中配置,如下
      图片、js包、css等都属于静态页面
    4. servlet。struts。springmvc 为什么能使用index.jsp能设置为默认首页,而index.html不能作为首页
      如果有index.jsp,没有index.html的情况,启动项目的时候,默认会访问index.jsp;
      如果有index.jsp,又有index.html的情况,启动项目的时候,会访问index.html,但是index.html属于静态资源,会被拦截,
      报错,需要在web.xml中配置放行才能访问,如下:
      如果在web.xml中配置了<welcome-file-list></welcome-file-list>的话,可以选择项目启动默认访问的页面。
         <!-- 配置springmvc的servlet的时候,使用的路径是"/",
         导致静态资源在默认情况下不能访问,所以要加上这一段,允许访问jpg。 并且必须加在springmvc的servlet之前 -->
         <servlet-mapping>
              <servlet-name>default</servlet-name>
              <url-pattern>*.jpeg</url-pattern>
              <url-pattern>*.jpg</url-pattern>
              <url-pattern>*.css</url-pattern>
              <url-pattern>*.js</url-pattern>
          	<url-pattern>*.html</url-pattern>
          </servlet-mapping>
  9. 拦截器 Interceptor
  10. 过滤器Filter:中文问题
  11. SpringMVC中使用REST风格的url
  12. SpringMVC与前台json数据交互,并应用ajax
  13. springmvc设计模式

知识点:

  1. Spring MVC 概念
    1. Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一部分,它和Struts2一样都属于表现层的框架。
    2. MVC(Model模型 View 视图 Controller 控制器):这是一种软件架构思想,是一种开发模式,将软件划分为三种不同类型的模块,分别是模型,视图,和控制器。
      1. 模型:用于封装业务逻辑处理(java类);
      2. 视图:用于数据展现和操作界面(Servlet);
      3. 控制器:用于协调视图和模型(jsp);
    3. 处理流程:视图将请求发送给控制器,由控制器选择对应的模型来处理;模型将处理结果交给控制器,控制器选择合适的视图来展现处理结果;
    4. 优点(和struts2相比)
      1. 和Spring 其他框架无缝集成,是其它Web框架所不具备的;
      2. RESTful风格的支持
      3. 和struts2相同
        1. 分工明确:
          前端控制器(DispatcherServlet)
          处理器映射(HandlerMapping)
          处理器适配器(HandlerAdapter)
          视图解析器(ViewResolver)
          处理器或页面控制器(Controller)
          验证器( Validator)
          命令对象(Command  请求参数绑定到的对象就叫命令对象)
          表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
        2. 数据绑定机制
        3. 注解实现
        4. 文件上传
        5. 中文问题
        6. 主题
        7. 本地化/国际化
  2. Spring MVC 架构:运行流程
    1. 运行流程:
      1. 客户端请求提交到DispatcherServlet
      2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
      3. DispatcherServlet将请求提交到Controller
      4. Controller调用业务逻辑处理后,返回ModelAndView
      5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
      6. 视图负责将结果显示到客户
    2. 五大组件说明:
      1. DispatcherServlet:前端控制器
        用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
      2. HandlerMapping:处理器映射器
        HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
      3. Handler:处理器
        Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
        由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
      4. 模型和视图(ModelAndView)
      5. View Resolver:视图解析器
        View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
  3. 基础
    1. spring mvc介绍、优点
      servlet、struts2和spring mvc三者的区别
    2. spring mvc使用流程
      1. 导包
      2. 配置web.xml
        <?xml version="1.0" encoding="UTF-8"?>
        <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
          <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        
            <!--springmvc配置文件默认和web.xml文件放在同一个目录下,如果放在跟目录下或其他目录下,需要声明-->
            <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:springMVC.xml</param-value><!--放在项目根目录下-->
            </init-param>
            <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
          </servlet-mapping>
        </web-app>
      3. 在WEB-INF目录下创建 springmvc-servlet.xml(名字需要和web.xml 中servlet-name的值相对应)
        <?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:aop="http://www.springframework.org/schema/aop"
            xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:mvc="http://www.springframework.org/schema/mvc"
            xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
        	
        	<!-- 第1种方法: 配置HandlerMapping ,根据beanname找到对应Controller -->
        	<!-- <bean class="org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping"></bean> -->
        	<!-- 配置Controller -->
        	<!-- <bean name="/index" class="controller.IndexController"></bean> -->  
        	
        
        	<!-- 第2种方法 :配置HandlerMapping ,根据简单URL,查找Controller-->
            <!-- <bean id="simpleUrlHandlerMapping"  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                <property name="mappings">
                    <props>
                        <prop key="/index">indexController</prop>
                    </props>
                </property>
            </bean>
            <bean id="indexController" class="controller.IndexController"></bean> -->
            
        
        	<!-- 第3种种方法 -->
        	<!-- 配置spring mvc 注解驱动,可不要 -->
        	<mvc:annotation-driven />
        	<!-- 注解扫描 -->
        	<context:component-scan base-package="controller"/>
        </bean>
      4. 写控制器:控制类 IndexController实现接口Controller ,提供方法handleRequest处理请求
        SpringMVC通过 ModelAndView 对象把模型和视图结合在一起
        表示视图是index.jsp
        模型数据是 message,内容是 “Hello Spring MVC”
        package controller;
         
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
         
        import org.springframework.web.servlet.ModelAndView;
        import org.springframework.web.servlet.mvc.Controller;
         
        public class IndexController implements Controller {
            public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
                ModelAndView mav = new ModelAndView("index.jsp");
                mav.addObject("message", "Hello Spring MVC");
                return mav;
            }
        }
    3. spring-mvc.xml配置文件详解
    4. 视图定位:将前端、后端、js、css等文件分类,一目了然
      使用流程:在spring-mvc.xml中配置即可
       <!-- 配置sprigmvc视图解析器:解析逻辑试图(配置jsp 显示ViewResolver)
                   后台返回逻辑试图:index
                  视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/page/*.jsp-->
          <bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
              <property name="prefix" value="/WEB-INF/pages/" />
              <property name="suffix" value=".jsp" />
          </bean>
    5. 使用注解实现:
      使用流程
      1. 控制器IndexController.java、配置文件springmvc-servlet.xml文件需要修改
      2. 配置spring-mvc.xml :开启注解和注解扫描
      3. 控制类使用注解:不用再实现Controller 接口 
    6. SpringMVC中注解和非注解方式下的映射器和适配器总结
      • 非注解
        处理器映射器:
        第一种:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
        第二种:org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
        处理器适配器:控制器
        第一种:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
        第二种:org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
        第三种:继承Contrlloer接口(最常用)
      • 注解
        注解映射器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping 
        注解适配器:控制器 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
        最优版:<context:component-scan base-package="controller"/>(最常用)
    7. 几个常用注解对象总结
      • @Controller:作用在类上,@Component注解的一个延伸,Spring会自动扫描并配置被该注解标注的类。此注解用于标注Spring MVC的控制器。
      • @RestController:是在Spring 4.0开始引入的,这是一个特定的控制器注解。此注解相当于@Controller和@ResponseBody的快捷方式。当使用此注解时,不需要再在方法上使用@ResponseBody注解。
      • @RequestMapping:作用在方法上,跟url有关(类上、方法上,两者的区别)
        • @GetMapping:用于处理HTTP GET请求,并将请求映射到具体的处理方法中。具体来说,@GetMapping是一个组合注解,它相当于是@RequestMapping(method=RequestMethod.GET)的快捷方式。
        • @PostMapping注解用于处理HTTP POST请求,并将请求映射到具体的处理方法中。@PostMapping与@GetMapping一样,也是一个组合注解,它相当于是@RequestMapping(method=HttpMethod.POST)的快捷方式。
        • @PutMapping注解用于处理HTTP PUT请求,并将请求映射到具体的处理方法中,@PutMapping是一个组合注解,相当于是@RequestMapping(method=HttpMethod.PUT)的快捷方式。
        • @DeleteMapping注解用于处理HTTP DELETE请求,并将请求映射到删除方法中。@DeleteMapping是一个组合注解,它相当于是@RequestMapping(method=HttpMethod.DELETE)的快捷方式。
        • @PatchMapping注解用于处理HTTP PATCH请求,并将请求映射到对应的处理方法中。@PatchMapping相当于是@RequestMapping(method=HttpMethod.PATCH)的快捷方式。
      • @RequestParam:作用在参数上,跟传参有关,可以进行参数绑定
      • @RequestBody:作用在参数上,@RequestBody直接以String接收前端传过来的json数据,接收的是一个Json对象的字符串,而不是一个Json对象
      • @ResponseBody:作用在方法上,一般放在@RequestMapping下面。@Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中
      • @PathVariable:跟REST有关, @PathVariable 注解,其用来获取请求路径(url )中的动态参数
        https://www.jb51.net/article/107791.htm
      • @ModelAttribute:通过此注解,可以通过模型索引名称来访问已经存在于控制器中的model
      • @ControllerAdvice
        @ControllerAdvice是@Component注解的一个延伸注解,Spring会自动扫描并检测被@ControllerAdvice所标注的类。@ControllerAdvice需要和@ExceptionHandler、@InitBinder以及@ModelAttribute注解搭配使用,主要是用来处理控制器所抛出的异常信息。
        首先,我们需要定义一个被@ControllerAdvice所标注的类,在该类中,定义一个用于处理具体异常的方法,并使用@ExceptionHandler注解进行标记。
        此外,在有必要的时候,可以使用@InitBinder在类中进行全局的配置,还可以使用@ModelAttribute配置与视图相关的参数。使用@ControllerAdvice注解,就可以快速的创建统一的,自定义的异常处理类。
        下面是一个使用@ControllerAdvice的示例代码:
        //指定特定的类生效(assignableTypes = HelloController.class))
        //指定所在的包生效(basePackageClasses={HelloController.class})
        @ControllerAdvice
        public class GlobalExceptionHandler  {
        	
        	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
        	
        	@ExceptionHandler(ArithmeticException.class)
        	// 或者 public ResponseEntity<Object> costomException(ArithmeticException e) {
        	public ResponseEntity<Object> costomException1(Exception e) {
        		logger.info("被除数不能为0", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "被除数不能为0");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
        	
        	@ExceptionHandler(ArrayIndexOutOfBoundsException.class)
        	// 或者 public ResponseEntity<Object> costomException(ArrayIndexOutOfBoundsException e) {
        	public ResponseEntity<Object> costomException2(Exception e) {
        		logger.info("数组索引越界异常", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "数组索引超出异常");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
        	
        	/**
        	 * @Description: 没有指定的异常走这里
        	 */ 
        	@ExceptionHandler
        	public ResponseEntity<Object> costomException(Exception e) {
        		logger.info("未知错误", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "未知错误");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
        	
        	@InitBinder
            public void InitBinder(WebDataBinder binder) {
                //前端传入的时间格式必须是"yyyy-MM-dd"效果!
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                CustomDateEditor dateEditor = new CustomDateEditor(df, true);
                binder.registerCustomEditor(Date.class, dateEditor);
            }
        }
      • @ExceptionHander注解:用于标注处理特定类型异常类所抛出异常的方法。当控制器中的方法抛出异常时,Spring会自动捕获异常,并将捕获的异常信息传递给被@ExceptionHandler标注的方法。需要和@ControllerAdvice搭配使用。
        下面是使用该注解的一个示例:
        @ExceptionHandler(ArithmeticException.class)
        	// 或者 public ResponseEntity<Object> costomException(ArithmeticException e) {
        	public ResponseEntity<Object> costomException1(Exception e) {
        		logger.info("被除数不能为0", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "被除数不能为0");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
        	
        	@ExceptionHandler(ArrayIndexOutOfBoundsException.class)
        	// 或者 public ResponseEntity<Object> costomException(ArrayIndexOutOfBoundsException e) {
        	public ResponseEntity<Object> costomException2(Exception e) {
        		logger.info("数组索引越界异常", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "数组索引超出异常");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
        	
        	/**
        	 * @Description: 没有指定的异常走这里
        	 */ 
        	@ExceptionHandler
        	public ResponseEntity<Object> costomException(Exception e) {
        		logger.info("未知错误", e);
        		Map<String, Object> result = new HashMap();
        		result.put("code", 1);
        		result.put("msg", "未知错误");
        		return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        	}
      • @InitBinder注解用于标注初始化WebDataBinider的方法,该方法用于对Http请求传递的表单数据进行处理,如时间格式化、字符串处理等。需要和@ControllerAdvice搭配使用。
        SpringBoot2教程29整合SpringMVC之@InitBinder处理请求参数的绑定(一) - 知乎
        下面是使用此注解的示例:
        	@InitBinder
            public void InitBinder(WebDataBinder binder) {
                //前端传入的时间格式必须是"yyyy-MM-dd"效果!
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                CustomDateEditor dateEditor = new CustomDateEditor(df, true);
                binder.registerCustomEditor(Date.class, dateEditor);
            }
      • @CrossOrigin注解:将为请求处理类或请求处理方法提供跨域调用支持。如果我们将此注解标注类,那么类中的所有方法都将获得支持跨域的能力。使用此注解的好处是可以微调跨域行为。
        47601b7d74e83ce889a829ad70bebfac.png
      • 说明:
        @responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,一般在异步获取数据时使用。需要注意的呢,在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
          @RequestMapping("/login")
          @ResponseBody
          public User login(User user){
            return user;
          }
         
          User字段:userName pwd
          那么在前台接收到的数据为:'{"userName":"xxx","pwd":"xxx"}'
         
          效果等同于如下代码:
          @RequestMapping("/login")
          public void login(User user, HttpServletResponse response){
            response.getWriter.write(JSONObject.fromObject(user).toString());
          }
        

    8. 参数绑定
      再加一种:
      @RestController
      @RequestMapping(path = "/user")
      public class InstitutionManagementController {
       
          @GetMapping(value = "/addUser")
          public void test(@ModelAttribute InstitutionQueryDTO queryDTO){
       
          }
      }
      
      这里的重点是@ModelAttribute注解,他也会将前端传过来的参数填充到业务实体中,前端传参格式与方法一相同。
      SpringMVC中的参数绑定总结
      【SpringMVC学习05】SpringMVC中的参数绑定总结_武哥聊编程的博客-CSDN博客_springmvc参数绑定
    9. 客户端跳转
  4. session 
  5. 上传文件
    使用流程:
    1. 在web.xml中配置:表示允许访问*.jpg。
      因为配置springmvc的servlet的时候,使用的路径是"/",导致静态资源在默认情况下不能访问,所以要加上这一段,允许访问jpg。 并且必须加在springmvc的servlet之前

      如果你配置spring-mvc使用的路径是/*.do,就不会有这个问题了。

      注: 这里仅仅是允许访问jpg,如果你要显示png,gif那么需要额外进行配置
    2. 	<servlet-mapping>
      	    <servlet-name>default</servlet-name>
      	    <url-pattern>*.jpg</url-pattern>
      	</servlet-mapping>
    3. 在springmvc-serlvet.xml中配置:支持文件上传
      </beans>
          ......
      
          <!-- 开放对上传功能的支持 -->
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
      </beans>
  6. 拦截器 Interceptor(对指定的请求进行拦截)
    1. 使用流程:
      1. 创建一个类实现拦截器接口
      2. 在spring-mvc.xml 中配置拦截哪些 url
        mvc:interceptors>   
                <!-- 对所有请求都拦截,公共拦截器可以有多个 -->
                <bean name="testInterceptor" class="interceptor.TestInterceptor" />
                <mvc:interceptor>   
                    <mvc:mapping path="/first/index"/> 
                    <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 
                    <bean class="interceptor.IndexInterceptor"/>     
                </mvc:interceptor> 
                <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法  -->
            </mvc:interceptors>
    2. 多个拦截器的使用
  7. 过滤器 Filter:
    解决中文问题
    方法一:在web.xml中配置一个 Filter过滤器
      <filter>
        <display-name>UTFFilter</display-name>
        <filter-name>UTFFilter</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>UTFFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    方法二:
    1. 创建一个类实现 Filter接口,设置编码为 utf8
    2. 在web.xml中配置该 Filter
        <filter>
          <display-name>UTFFilter</display-name>
          <filter-name>UTFFilter</filter-name>
          <filter-class>filter.UTFFilter</filter-class>
        </filter>
        <filter-mapping>
          <filter-name>UTFFilter</filter-name>
          <url-pattern>/*</url-pattern>
        </filter-mapping>
  8. 过滤器和拦截器结合
  9. 在SpringMVC中使用REST风格的url(get查、post增、put改、delete删)
  10. 浅谈springMVC中的设计模式(1)——责任链模式
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值