ssm知识点整合

spring

IOC

出现原因:原项目中,接口=创建实现类,如果有大量这样的语法需要修改时,会面临着改大量的文件,这是高耦合时的弊端。如果想解耦,那么就不自己创建变量实例即可。
实现方式有两种。一个能创建实例的工具,创建对象后,赋值给需要的变量。(相当于EE阶段写的autoinject工具), 另一种是需要赋值的对象,有容器创建,创建好后,
自动赋值想要的数据。因为是容器创建的对象,所以这个容器也很容易管理这个对象,那么整个项目中大部分的资源都是该容器创建的话,就可以用语言描述的方式,
快速获取赋值了某些数据的对象。(这里我们归纳出了工厂设计模式)。这容器就是spring框架的主体,可以用配置文件.xml来描述要创建哪些实例对象,
并且描述那些实例对象需要注入什么数据。

DI

依赖注入(对象里面的变量、属性都是由容器给的,不是自己创建的)

IOC 控制反转思想(容器来管理对象)

AOP

出现原因:原项目中,如果在相同层,不同功能模块地方,具有相同特征的地方。比如说所有的数据库链接,所有的的业务层,所有的查询业务,所有的修改业务,所有登录下访问的业务
进行执行流程上的修改时,维护成本过高。OOP AOP,面向对象编程,按照执行顺序。找到相同点, 作为切点。编写切面类,根据通知将切面的功能织入。

tx

 1,什么是事务: a? c? i? d?

ACID:
原子性(Atomicity)
事务的原子性是指事务是一个不可分割的工作单位,这组操作要么全部发生,否则全部不发生。
一致性 (Consistency)
一个账号两个操作,例,一个账号先减一次五,在减一次五,那么这两个操作他们最终的结果都是减十,大家操作的同一组数据,面对同一个结果。
在事务开始以前,被操作的数据的完整性处于一致性的状态,事务结束后,被操作的数据的完整性也必须处于一致性状态 。
拿银行转账来说,一致性要求事务的执行不应改变A、B两个账户的金额总和。如果没有这种-致性要求,转账过程中就会
发生钱无中生有,或者不翼而飞的现象。事务应该把数据库从一个一致性状态转换到另外一个一致性状态。
隔离性( Isolation)
事务隔离性要求系统必须保证事务不受其他并发执行的事务的影响,也即要达到这样一种效果:对于任何一-对事务TI和T2,
在事务TI看来,T2要么在TI开始之前已经结束,要么在TI完成之后才开始执行。这样,每个事务都感觉不到系统中有
其他事务在并发地执行。
持久性(Durability)
一个事务一旦成功提交,它对数据库的改变必须是永久的,即便是数据库发生故障也应该不回对其产生任何影响。

   2, 事务解决哪几个问题,他们的解决方案是什么:

隔离机制要解决的数据库事务问题分为3个层次。脏读, 幻读,不可重复读。
脏读:两组事务的处理共享同组数据, 事务处理过程中的结果会被其他事务访问(事务未提交) 。
两组事务处理一组数据,能够访问另一个事务未提交的数据
10-5 2 10
5_-5_-10_ 0
10 -10 +10 10
解决思路:未提交的事务不能访问
以下是已解决脏读会出现的问题
不可重复读: a事务搜索数据,b事务修改的数据提交后,a再次搜索得到的数据不一样。T
原数据Abcd
a事务搜索Abed
b事务修改nna,提交
a事务搜索a8a
两次搜索结果不一致, 这里强调的是a事务(事务! !没有中断情况下)
解决思路:将a事务所有搜索的资源加读锁,(行级锁,把所有搜索到的数据上锁,他是写锁)a事务末解决完,其他事务只能看不能改。必须耍知道锁定什么资源,也就是
where子句运行后,上锁。这里有个漏洞,(引出)无法锁定未知的资源!!!!(因为只能锁住已知资源无法锁住未知资源,所以出现了幻读,所以幻读是添加)。
幻读: a事务搜索数据,b事务插入析的数据提交后,a再次搜索得到的数据不一样。
原数据有3条
a事务搜索3条
b事务增加1条
a事务搜索4条
两次搜索结果,条数不一致,这里强调的是a事务(事务!↓没有中断情况下)
解决思路:可以直接锁定被搜索的资源所在的表的占用空间。也称为锁表。(直接锁住写功能,让它只能看)
解决思路2:数据库中同一时间只有一个事务运行。(单线程,序列化)
也是mysql和oracle的他们的设计思路

3,   spring有哪些事务解决方案(事务隔离机制) :
 3+1+1
   事务隔离
   isolation_ default
   这是一个PlatfromTransact ionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔
   离级别相对应
  isolation_ read uncommitted
   这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可
   重复读和幻像读
   isolation_ read committed
   保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务
   隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
   isolation repeatable read
    这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事 务不能读取另一个事 务未
    提交的数据外,还保证了避免下面的情况产生(不可重复读)。
   isolation serializable
   这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了
   幻像读。
   
  4, 什么是事务的传播机制,为什么会有事务传播机制:

写项目时,每一次连接都需要开关数据库,这样性能消耗太大
把开关用一次代替,数据库连接池c3p0
事务传播机制出现的原因是,(前提.事务的控制都在sevice层)因为在service多层嵌套,叠加业务混乱,不知道该听谁的,所以有了事务传播机制
数据库连接池也是由spring容器来创建,然后就可以管理了,连接池也是一个小容器,里面有各种数据库连接,spring相当于可以
从这里提取连接,分配,怎么分配,靠AOP,由此,通过AOP进行事务控制
事务七个传播机制
propagation required 能用外出的用外出,外层没有开新的
如果存在一个事务,则支持当前事务。如果没有事务则开启-个新的事务。 (默认)
默认的spring事务传播级别,使用该级别的特点是,如果上下文中已经存在事务,那么就加
入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景。
propagation supports 外层啥样里层啥样
如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的
事务管理器,propagation supports与不使用事务有少许不同。
从字面意思就知道,supports, 支持,该传播级别的特点是,如果上下文存在事务,则支持事
务加入事务,如果没有事务,则使用非事务的方式执行。所以说,并非所有的包在transac t ionTemplate. execute中的代码
都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。应用场景较少。
propagation mandatory 必须能用到外层的事务,没有报错
如果已经存在一一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
该级别的事务要求 上下文中必须要存在事务,否则就会抛出异常!配置该方式的传播级别是
有效的控制上下文调用代码遗漏添加事务控制的保证手段。比如一段代码不能单独被调用执行,但是一旦被调用,就必须有
事务包含的情况,就可以使用这个传播级别。
propagation requires new 强制新事物,自己用自己的
总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
从字面即可知道,new, 每次都要- 个新事务,该传播级别的特点是,每次都会新建一- 个事
务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。
这是一个很有用的传播级别,举一个应用场景:现在有一个发送100个红包的操作,在发送之前,要做一些系统的初始化、
验证、数据记录操作,然后发送100封红包,然后再记录发送日志,发送日志要求100%的准确,如果日志不准确,那么整个
父事务逻辑需要回滚。
怎么处理整个业务需求呢?就是通过这个propagation requires new级别的事务传播控制就可以完成。发送红包的子事务
不会直接影响到父事务的提交和回滚。
propagation not_ supported 不用事务,最小粒度处理
总是非事务地执行,并挂起任何存在的事务。
这个也可以从字面得知,not supported ,不支持,当前级别的特点就是上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文的事务。
这个级别有什么好处?可以帮助你将事务极可能的缩小。我们知道一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,要保证尽可能的缩小范围。
比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。这样的代码如果包在事务中,势必造成事务太大,
导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。用当前级别的事务模板抱起来就可以了。
propagation never 谁都不能用事务,最小粒度处理
总是非事务地执行,如果存在一个活动事务,则抛出异常
该事务更严格,上面一个事务传播级别只是不支持而已,有事务就挂起,而propagation never
传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!这个级别上辈子跟事务有仇。
propagation nested Spring的事务传插机制
如果一个活动的事务存在,则运行在一个嵌套的事务中, 如果没有活动事务,则按
TransactionDef inition. propagation required属性执行
字面也可知道,nested, 嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事
务执行,如果不存在事务,则新建事务。

悲观锁、乐观锁

   悲观锁是语法上加上锁关键字,强制其他会话不可访问。
   乐观锁是建模设计上加锁字段,筛选乐观锁字段来限制资源访问。
  乐观锁一般是在where语句中加乐观镜字段匹配,在更新语句和插入语句中每次修改乐观锁字段值
  悲观锁一般是在搜索语句后加for update 语句,锁定搜索覆盖的数据,让资源冲灾的语句等待运行。可以加wait 关键字
  设定是否有等待超时,等待超时后报错结束语句。
  悲观锁语法
  select sql + for update
  select sql + for update nowait
  select sql + for update wait 10(s)

constructor-arg: constructor arguments, 构造函数的参数。
      使用构造子注入时,则使用constructor-arg子标签,来指定构造函数的参数。
------一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一

具体代码实现

IOC

注册
 <bean id/name class>
   <constructor-arg></constructor-arg>
  </bean>
  获取方法返回值
  实例工厂方法
  静态工厂方法
  <context:component-scan base-package="root.controller" />
   @Controller
   @Service
   @Component
   @Repository
   四种注册方式,名字不同功能先沟通。
注入
 xml
<property name="" ref="" value="">
  <list></list>
  <set></set>
  <map></map>
 <array></array>
</property>

注解

@Autowired/@Qualifier bean实例的名字@primary
@Resource(name="" type="")bean写入
—@inject/@named
@Required注释为为了保证所对应的属性必须被设置,@Required 注释应用于 bean 属性的 setter 方法,
它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。
下面显示的是一个使用 @Required 注释的示例。直接的理解就是,如果你在某个java类的某个set方法上使用了该注释,
那么该set方法对应的属性在xml配置文件中必须被设置,否则就会报错!!!
当使用@Autowired(required=false)时,即使找不到
合适的IUserDao对象注入,也可以
这个就是多态。zhidao UserManager实例化的时候肯定要传一个实现接口IUserDAO的UserDAO对象。专 private IUserDAO userDao.
代表的是userDao的对象类型时IUserDAO,其实实际调用属的是它的实现类。

aop

编写切面类
编写切面类
//前置通知
public void method(JoinPoint jp)
//后置通知
public void method(0bject o)
//异常通知
public void method(JoinPoint jp, Throwable ta)
//最终通知
public void method()
//环绕通知
public void method(ProceedingJoinPoint pjp)

注册aop
xml
        <bean id="" class=""></bean>       注册切面.
        <aop : config>
       <aop :pointcut expression="" id=""/>      创建切点
       <aop:aspect ref="" order="">                  创建通知
       <aop: before method="" pointcut-ref=""/>
       <aop : after-returning method="" pointcut-ref-"" returning=""/>
      <aop:after method="" pointcut -ref="pc1"/>
      <aop: after - throwing method="" pointcut-ref="" throwing=""/>
     <aop :around method="" pointcut-ref=""/>
     </aop: aspect>
     </aop: config>
注解
   <aop: aspectj- autoproxy></aop :aspectj - autoproxy>
  @Aspect
  @Order()
 @Pointcut()
 @Before
 @AfterReturning(returning = "", pointcut = "")
 @AfterThrowing(pointcut = "",throwing = ")
 @After(")
 @Around("")
tx
创建jdbc数据源(不是数据库连接池)
     <bean id= ”datasource" class="org. springframework . jdbc . datasource .DriverManagerDataSource">
             <property name="driverClassName" value="oracle. jdbc . driver .0racleDriver"></ property>
             <property name="url" value=" jdbc:oracle:thin:@127.0.0.1:1521:orc1" ></ property>
             <property name="username" value-=""></property>
             <property name=" password" value=""></property>
    </bean>
    创建事务控制器
     <bean name="transactionManager" class="org. springframework . jdbc . datasource . DataSourceTransactionManager>
     <property name= "dataSource" ref=" dataSource" ></ property>
   </bean>
   配置事务控制器两种方式
     <tx:advice id="txAdvice_ NAME" transaction-manager=" transactionManager">
     <tx:attributes>
    <!--以方法为单位,指定方法应用什么事务属性isolation:隔离级 别propagation:传播行为read-only:是否只读->
    <tx:method name="save*" isolation=" propagation="" read -only="" />
    <tx:method name=" persist*" isolation="" propagation="" read-on1y="" />
    <tx :method name=" update*" isolation="" propagation="" read- only="" />
    <tx:method name= "modify*" isolation="" propagation="" read-on1y="" />
    <tx:method name="delete*" isolation="" propagation="" read -only="" />
   <tx:method name="remove*" isolation="" propagation="" read-on1y="" />
   <tx:method name="get*" isolation="" propagation="" read-only="" />
   <tx:method name="find*" isolation="" propagation="" read-only="" />
   <tx:method name="select*" isolation="" propagation="" read-only="" />
  </tx:attributes>
 </tx:advice>
<aop: config>
    <!--配置切点表达式-->
  <aop:pointcut expression="" id="txpoint" />
 <!--配置切面:通知+切点advice -ref:通知的名称pointcut-ref:切点的名称->
<aop: advisor advice-ref="txAdvice_ NAME”pointcut-ref="txpoint" />
</aop:config>
注解
 @Transactional(isolation =隔离级别, propagation =传播机制)
@Transactional(isolation = Isolation. REPEATABLE READ,propagation = Propagation. REQUIRED)

springmvc

出现的问题:

         因为EE规范使用自己的servlet实例,spring的I0C 无法注入数据给EE的servlet.
         返回的视图路径与文件存放位置和技术栈高度耦合,无法随意更换文件的存放路径,和技术栈。
         (为什么出现更换文件位置的情况,目前所有页面都存在了web服务器下,既tomcat, 但实际上运营是将静态资源存储到文件服务器上。
         这样可以分担web服务器数据传输压力,这种设计思路称为动静分离)

问题都有什么解决方案:

        servlet既然不能注入,那么就给一个统一 的servlet。 让servlet 去根据路径调用不同的类,实现原servlet的功能。这时候调用的类就可以由
       spring管理,就能够实现自动注入功能。
       返回的不再是完整路径,只返回子目录和文件名就可以。之后统一-拼接根目录和技术栈,这样就不需要因页面的维护,连带后台代码的维护。

框架提出什么方案,怎么设计的:

      加上以前的推导!!!!!!!就是那个图
     1.用户发送请求至前端控制器DispatcherServlet。
     2.前端控制器DispatcherServlet收到请求后调用处理器映射器HandlerMapping。
    3.处理器映射器HandlerMapping根据请求的Url找到具体的处理器,生成处理器对象Handler及处理器拦截器HandlerIntercepter(如果有则生成)一并返回给前端控制器DispatcherServlet。
             为什么出现拦截器,因为要先执行servlet才执行中央处理器,才能开始业务处理,而此时过滤器已经过了。
    4.前端控制器DispatcherServlet通过处理器适配器HandlerAdapter调用处理器Controller。
   5.执行处理器( Controller, 也叫后端控制器)
   6.handler 处理器Controller执行完后返回ModelAndView。
   7.处理器适配器HandlerAdapter将处理器Controller执行返回的结果ModelAndView返回给前端控制器DispatcherServlet。
   8.前端控制器DispatcherServlet将ModelAndView传给视图解析器ViewResolver。
   9.视图解析器ViewResolver解析后返回具体的视图View。
  10.前端控制器DispatcherServlet对视图View进行渲染视图(即:将模型数据填充至视图中)
  11.前端控制器DispatcherServlet 响应用户
   网址映射handler
    @controller
    @reques tmapping(value/path method)
     --------------------------------------------------------------------------
    <mvc : annotation-driven enable -matrix -variables="true" />
   @restcontroller
   @PutMapping(value/path)
   @DeleteMapping(value/path)
   @PostMapping(value/path)
   @GetMapping(value/ path)
资源绑定
     四类: ( 主要讲解常用类型)
     A、处理request uri部分的注解: @PathVariable;
     B、处理request header 部分的注解: @RequestHeader, @CookieValue;
     C、处理request body部分的注解: @RequestParam, @RequestBody;
     D、处理attribute类 型是注解: @SessionAttributes ,@SessionAttribute, @ModelAttribute;
	      model是社么?
	       使用模型@valid Vo   1类型转换规则     2检查     3嵌套
视图解析
   <bean class= "org . springframework . web . servlet. view. InternalResourceViewResolver">
   <!--这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个可用的ur1地址->
   <property name=" prefix" value=" /WEB-INF/jsp/" />
   <property name=" suffix" value=" .jsp" />
  </bean>
拦截器
   拦截器 与过滤器区别:部署位置,技术栈,执行流程
   拦截器流程
   部署正序执行preHandle,
   如果返回true执行handler,倒序执行postHandle,倒序执行afterCompletion
   如果返回false停止当前处理链的preHandle,越过postHandle, 从当前拦截器倒序执行afterCompletion
编写拦截器
   public class Interceptor2 implements HandlerInterceptor 
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
   throws Exception {
   return false;
   public void postHandle (HttpServletRequest request, HttpServletResponse response, object handler,
  ModelAndView modelAndView) throws Exception {
  public void afterCompletion(HttpServ1etRequest request, HttpServletResponse response, object handler, Exception ex)
  throws Exception {
   }
  } 
配置拦截器
  <mvc: interceptors>
  <mvc:interceptor>
  <mvc:mapping path="" />
  <ref bean=""/>
  </mvc : interceptor>
 </mvc:interceptors>
 对于静态资源处理有三种
                web . xml                        springmvc . xml
  1.              /                                  <mvc :default-servlet-handler />
  2.              /                                 <mvc:resources mapping=" /js/**" location="resource/js/" /><mvc:resources mapping="/css/**" location="resource/css/" 1>
  3.             .do .action ...               不处理
   异常处理.
    @ControllerAdvice
     public class Errorpath {
    @ExceptionHandler(Exception. class)
    public String errorpath1(Exception e) {
    System. out .print1n(e);
    return "error";
     }

Mybatis

开关数据库 不能总去开关数据库,浪费资源,慢!mybatis不管开关数据库,直管connection
开关事务,调节事务隔离级别 得到connection后,mybatis 创建会话,在会话中使用分配到的connection
编写sql语句, 根据需求产生动态sql语句 where子句模糊查询逻辑拼接表链接
填充占位符 解析模型层,顺序对号入座{框架中是按占位符名字对号入座}
执行增删改查 框架反射自动执行
查询有结果集 增删改有条数
结果集转存至模型集合 解析结果集,生成多种类型的返回结果。( mybatis的优势)

在使用传统JDBC时,我们往往需要写很多JDBC代码,需要自己写SQL语句以及自己装配参数,然后自己对结果集进行封装处理,而Mybatis帮我们简化了以上功能,只需要一些配置文件(xml)或是注解的方式即可完成对数据库的查询以及结果的映射封装。

首先Mybatis是一个优秀的持久化框架,它支持自定义SQL查询、存储过程,和很好的一个映射。第二点Mybatis减少了大部分JDBC的代码,避免了手动设置参数和结果集的映射。第三点Mybatis用简单的XML配置文件或注解来配置映射关系,将接口和POJO对象映射到数据库记录中。

id唯一标识, 可以将mapper与接口的方法相连
resultType 自动映射简单的模型对象 根据反射内省自动注入简单模型autoinject()
resultMap 自动映射复杂的模型对象 未实现过,是mybatis的一 大优势
parameterType 根据模型对象注入参数 根据反射内省自动注入,autopstm()

研究缓存后期细讲,分为一级二级
开启缓存useCache="true "
清理缓存flushCache="true "

继续研究多数据库类型兼容开发的sq1
databaseId="”会将 某个id的mapping配置绑定给某个数据源。

dao接口 + mybatis的mapper . xml对应,描述这个功能怎么实现
数据库connection的配置。 所以还有一个配置文件mybatis的配置文件

使用redirect:、forward: 后不走视图解析器,跳转 可以跳到另一个handler
@requestmapping (“/demo” )
Public String demo() {
Return“ forward: / index
model是一个Map结构的数据模型,能重定向时传递数据(拼接URL),但不安全,主要用于渲染前端页面,配合Thymeleaf
填充html里面里设置好的参数。
@RequestParam用来获取查询字符串的参数值。
HttpServletRequest也可以获取查询字符串的参数值。
redirect:用 于重定向到新的url。
@ModelAttribute:运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入
ModelMap中,便于View层使用。
@ModelAttribute:运用在方法.上,会在每- -个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入
到ModelMap中。
redi rectAttribute. addAttribute实现URL字符串拼接,类似于mode 1. addAttribute,但是它并不把数据添加到model里。
redi rectAt tribute. addF lashAt tribute是安全的传参方法。
Model架空了request重定向时, 自动将 已经存储在request中的数据用? Key=value 方式转发至新路径上。此时会暴露敏感信息
redi rectAttribute. addAttribute 和model一样转存拼接,但是不保留,不存进model
redi rectAttribute. addF lashAttribut 解进了敏感数据在地址栏传输不安全问题,还有地址栏只能传输字符

参数(Parameters)
字符串替换#{} ${}
默认情况下,使用#{} 格式的语法会导致MyBatis创建PreparedStatement参数并安全地设置参数(就像使用?一样)。这样做更安全,更迅速,通常也是首选做法,
不过有时你就是想直接在SQL 语句中插入一个不转义的字符串。比如,像ORDER BY,你可以这样来使用: select * from demo where ? = 'abc’ X
select * from tablename where $ (colname} is null
ORDER BY $ {colunnName}
这里MyBatis不会修改或转义字符串。
#{}是pstm 的set方法
是 简 单 的 字 符 串 拼 接 。 那 么 在 使 用 {}是简单的字符串拼接。那么在使用 使}时会出现sql注入

动态sql
MyBatis的强大特性之一便是它的动态 SQL.如果你有使用JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接SQL 语句的痛苦。例如拼接
时要确保不能忘记添加必要的空格。还要注意去掉列表最后一个列名的逗号。利用动态SOL这一特性 可以彻底摆脱这种痛苦。
虽然在以前使用动态SQL并非一件易事, 但正是MyBatis提供了可以被用在任意SQL映射语句中的强大的动态SQL语言得以改进这种情形。
动态sQL,元素和JSTL 或基于类似XIL的文本处理器相似。在MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis3大大精简了元素种类,
现在只需学习原来一-半的元素便可。MyBatis采用功能强大的基于OCNL 的表达式来淘汰其它大部分元素。
if
choose (when, otherwi se)
trim (where, set)
foreach

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值