【基于SSH框架的个人博客系统01】Eclipse搭建SSH框架详细流程

Eclipse搭建SSH框架搭建教程

 

前期环境准备:

①   Java环镜

②   Eclipse4.6.2

③   Tomcat8.5

④   Struts2.3.41

⑤   Spring4.2.4

⑥   Hibernate4.3.11

⑦   mysql-5.6.35-winx64

⑧   Mysql-connector-java-5.1.26

⑨   Navicat for MySQL

其中①②③可以参照http://www.cnblogs.com/oucbl/p/5928511.html。

对于SSH框架的搭建,本人主要是参照http://blog.csdn.net/eson_15/article/details/51277324这篇博客来搭建的框架,其中的④⑤⑥⑦可以在里面下载到。

 


SSH框架各自的作用:

在开始搭建框架之前,先整体讲一下SSH框架各自的用途。首先是Struts框架,众所周知,一个网页有着各种各样的请求,比如注册账号,登录账号等请求,通过配置Struts框架,这些请求都会被拦截,由我们分配的Action进行处理,然后再根据我们的配置文件来进行转发。其次是Hibernate框架,它实现了数据库表与javabean的一一对应,使我们能够通过操纵类来操纵数据库。最后是Spring框架,它实现了SSH框架之间的解耦,通过配置文件,我们可以实现依赖注入。比如我有一个类A,其中有一个成员是类B,那么使用之前我们都需要先得到这个类的一个实例,正常情况下我们是通过new来实现。但是,使用了Spring框架之后,我们就可以通过配置文件将B依赖注入进A,在使用时不用管这个类的创建,只负责使用,大大方便了开发。可以说Spring框架就是SSH框架中的粘合剂,掌管着里面各个类。


开始搭建


首先附上项目目录结构图




第一步:新建项目

新建一个Dynamic Web Project项目。然后右键点击项目-Properties-Java Build Path,将默认输出路径调整到项目目录下的WEB-INF/classes。(之后会解释)



第二步:搭建Struts框架

①   进入WEB-INF中的lib,把struts所需jar包复制进来,之后右键项目刷新。(之后每次在eclipse之外的操作都要刷新项目,不再重复)

②   修改WEB-INF目录下的web.xml如下:

[html]  view plain  copy
  1. <?xml version="1.0"encoding="UTF-8"?>  
  2.    <web-appxmlns:xsiweb-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.        xmlns="http://java.sun.com/xml/ns/javaee"  
  4.        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  5.        id="WebApp_ID" version="2.5">  
  6.    <display-name>S2SH</display-name>  
  7.    
  8.    <filter>  
  9.            <filter-name>struts2</filter-name><!--这里的名字要和下面一致 -->  
  10.            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  11.    </filter>  
  12.    
  13.    <filter-mapping>  
  14.            <filter-name>struts2</filter-name>  
  15.            <url-pattern>/*</url-pattern>  
  16.    </filter-mapping>  
  17.    <welcome-file-list>  
  18.            <welcome-file>index.jsp</welcome-file>  
  19.    </welcome-file-list>  
  20.    <listener>   
  21.    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
  22.     </listener>  
  23. </web-app>  


③   新建一个TestAction类进行Struts框架的测试

[java]  view plain  copy
  1. package com.blog.action;  
  2. importcom.opensymphony.xwork2.ActionSupport;  
  3.    
  4. public class TestAction extendsActionSupport{  
  5.        publicString execute() throws Exception{  
  6.               System.out.println("Struts2测试成功!!");  
  7.               return"success";  
  8.        }  
  9. }  

④   在src目录下,新建struts.xml,内容如下:

[html]  view plain  copy
  1. <?xml version="1.0"encoding="UTF-8" ?>  
  2.    <!DOCTYPE struts PUBLIC  
  3.            "-//Apache Software Foundation//DTD Struts Configuration2.0//EN"  
  4.            "http://struts.apache.org/dtds/struts-2.0.dtd">  
  5.    
  6.    <struts>  
  7.        <package name="default"extends="struts-default">  
  8.            <action name="login" class="com.blog.action.TestAction">//类的目录  
  9.                   <resultnameresultname="success">/index.jsp</result>  
  10.               </action>  
  11.        </package>  
  12.    </struts>  
  13.    


⑤   在WebContent下新建index.jsp,之后都利用这个页面来检测。

[html]  view plain  copy
  1. <%@ page language="java"contentType="text/html; charset=UTF-8"  
  2.    pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <metahttp-equivmetahttp-equiv="Content-Type" content="text/html; UTF-8">  
  7. <title>Insert titlehere</title>  
  8. </head>  
  9. <body>  
  10.        <ahrefahref="login.action">访问save</a>  
  11. </body>  
  12. </html>  


总结:

解释一下在这里struts框架的作用。在Web.xml配置了之后,所有符合/*的链接都会被Struts框架中的org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter拦截链接,根据struts.xml的配置来进行转发,这里我们是转发到com.blog.action.TestAction这个类的public String execute()来处理,根据返回的String来转发网页。在struts中的配置有一个<resultname="success">/index.jsp</result>,即如果返回了success,就跳到/index.jsp这个网页。这是struts的一个用途。

 


 

第三步:搭建Spring框架并且组合Struts框架

①   将Spring所需jar包拉进lib中。

②   在web.xml添加如下内容:

[html]  view plain  copy
  1. <listener>   
  2.    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
  3.     </listener>   
  4.      
  5.    <context-param>   
  6.    <param-name>contextConfigLocation</param-name>   
  7.    <param-value>classpath:applicationContext.xml</param-value>   
  8. </context-param>   

③   在src目录下新建一个applicationContext.xml,内容如下:

[html]  view plain  copy
  1. <?xml version="1.0"encoding="UTF-8"?>  
  2.    <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:aop="http://www.springframework.org/schema/aop"  
  5.        xmlns:tx="http://www.springframework.org/schema/tx"  
  6.        xmlns:context="http://www.springframework.org/schema/context"  
  7.        xsi:schemaLocation="  
  8.       http://www.springframework.org/schema/beans  
  9.       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  10.       http://www.springframework.org/schema/tx  
  11.       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
  12.       http://www.springframework.org/schema/context  
  13.       http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  14.       http://www.springframework.org/schema/aop  
  15.       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" >  
  16.        <bean id="date" class="java.util.Date" />  
  17.        <bean id="TestAction"class="com.blog.action.TestAction"scope="prototype">   
  18.        <property name="date" ref="date" />  
  19.        </bean>  
  20. </beans>   

④   将struts中对应的class交给spring来管理,class后面的内容改为applicationContext.xml对应bean的id。

[html]  view plain  copy
  1. <action name="login"class="TestAction">  
  2.         <result name="success">/index.jsp</result>  
  3.  </action>  

⑤   将TestAction改为

[java]  view plain  copy
  1. package com.blog.action;  
  2. import java.util.Date;  
  3. import org.hibernate.HibernateException;  
  4. import org.hibernate.Session;  
  5. import org.hibernate.SessionFactory;  
  6. import org.hibernate.Transaction;  
  7. importorg.hibernate.boot.registry.StandardServiceRegistryBuilder;  
  8. importorg.hibernate.boot.registry.internal.StandardServiceRegistryImpl;  
  9. import org.hibernate.cfg.Configuration;  
  10. importorg.hibernate.service.ServiceRegistry;  
  11. importcom.opensymphony.xwork2.ActionSupport;  
  12. public class TestAction extendsActionSupport{  
  13.        privateDate date;  
  14.        publicvoid setDate(Date date){  
  15.               this.date=date;  
  16.        }  
  17.        publicDate getDate(){  
  18.               returndate;  
  19.        }  
  20.        publicString execute() throws Exception{  
  21.               System.out.println("Struts2测试成功!!");  
  22.               System.out.println("Spring测试:目前时间是:"+date);  
  23.               return"success";  
  24.        }  
  25. }  

总结:

解释一下Spring框架在这里的作用。Spring框架利用IOC的思想,减少了框架之间的耦合程度。比如,在TestAction中,我并没有对date进行new操作就直接使用,而是利用配置文件,在“无形之中”完成了date的创建。首先我们在web.xml配置spring框架的监听器,并且让程序一开始就读取spirng框架的配置文件。

[html]  view plain  copy
  1. <context-param>   
  2.    <param-name>contextConfigLocation</param-name>   
  3.    <param-value>classpath:applicationContext.xml</param-value>   
  4. </context-param>   

这一段中的classpath:指的就是WEB-INF-classes这个路径。它会到这个路径下寻找applicationContext.xml并读取。在配置文件中

[html]  view plain  copy
  1. <bean id="date"class="java.util.Date" />  
  2. <bean id="TestAction"class="com.blog.action.TestAction"scope="prototype">   
  3. <property name="date"ref="date" />  
  4. </bean>  

其实就完成了对date的创建,这个仔细琢磨一下应该能看懂。

由于我们使用spring来管理类的创建,所以struts 中action的class也改为ApplicationContext.xml中对应bean的id。

 

第四步,搭建Hibernate环境

①   将hibernate框架及数据库连接所需要用的jar包拉进lib中。

②   这里我们先使用到Navicat来完成对数据库的创建。



③   接下来创建Dao层,DaoImpl层,以及bean层。

[java]  view plain  copy
  1. package com.blog.dao;  
  2. import org.hibernate.HibernateException;  
  3. import org.hibernate.Session;  
  4. public interface BaseDao {   
  5.    public void saveObject(Object obj) throws HibernateException;   
  6.    public Session getSession();   
  7.    public void setSession(Session session);   
  8. }   
  9.    
  10. package com.blog.daoImpl;  
  11. import org.hibernate.HibernateException;  
  12. import org.hibernate.Session;  
  13. import com.blog.dao.BaseDao;  
  14. public class UserDao implements BaseDao{   
  15.    private Session session;   
  16.    @Override   
  17.    public Session getSession() {   
  18.         return session;   
  19.    }   
  20.    @Override   
  21.    public void setSession(Session session) {   
  22.        this.session = session;   
  23.    }   
  24.    @Override   
  25.    public void saveObject(Object obj) throws HibernateException {   
  26.        session.save(obj);   
  27.     }   
  28. }   
  29. public class User {  
  30.        privateString username;  
  31.        privateString password;  
  32.        privateInteger id;  
  33.        publicString getUsername() {  
  34.               returnusername;  
  35.        }  
  36.        publicvoid setUsername(String username) {  
  37.               this.username= username;  
  38.        }  
  39.    
  40.        publicString getPassword() {  
  41.               returnpassword;  
  42.        }  
  43.    
  44.        publicvoid setPassword(String password) {  
  45.               this.password= password;  
  46.        }  
  47.        publicvoid setId(Integer id){  
  48.               this.id=id;  
  49.        }  
  50.        publicInteger getId(){  
  51.               returnid;  
  52.        }  
  53. }  

③   在src目录下新建hibernate.cfg.xml和User.hbm.xml。

Hibernate.cfg.xml内容如下:

[html]  view plain  copy
  1. <?xml version="1.0"encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC  
  3. "-//Hibernate/Hibernate ConfigurationDTD 3.0//EN"  
  4. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  5. <hibernate-configuration>  
  6.    <session-factory>  
  7.         <!-- 各属性的配置-->  
  8.        <!-- 为true表示将Hibernate发送给数据库的sql显示出来 -->  
  9.        <property name="show_sql">true</property>  
  10.        <!-- SQL方言,这边设定的是MySQL -->  
  11.        <propertynamepropertyname="dialect">org.hibernate.dialect.MySQLDialect</property>  
  12.          
  13.        <!-- 一次读的数据库记录数 -->  
  14.        <property name="jdbc.fetch_size">50</property>  
  15.          
  16.        <!-- 设定对数据库进行批量删除 -->  
  17.        <property name="jdbc.batch_size">23</property>  
  18.          
  19.        <!--驱动程序-->  
  20.        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  
  21.          
  22.        <!-- JDBC URL -->  
  23.        <propertynamepropertyname="connection.url">jdbc:mysql://localhost/mankind</property>  
  24.          
  25.        <!-- 数据库用户名-->  
  26.        <propertynamepropertyname="connection.username">root</property>  
  27.          
  28.        <!-- 数据库密码-->  
  29.        <propertynamepropertyname="connection.password">123456</property>  
  30.         <!--数据库连接池的大小-->    
  31.        <property name="hibernate.connection.pool.size">20</property>   
  32.        <!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率-->    
  33.        <property name="hibernate.show_sql">true</property>    
  34.        <!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->    
  35.        <property name="jdbc.use_scrollable_resultset">false</property>    
  36.        <!--connection.useUnicode连接数据库时是否使用Unicode编码-->    
  37.        <property name="Connection.useUnicode">true</property>   
  38.        <!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->  
  39.        <property name="connection.characterEncoding">gbk</property>   
  40.        <!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->    
  41.        <propertynamepropertyname="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>    
  42.        <!--指定映射文件为“hibernate/ch1/UserInfo.hbm.xml”-->           
  43.        <mapping resource="User.hbm.xml"/>    
  44.    </session-factory>  
  45. </hibernate-configuration>  

User.hbm.xml内容如下:

[html]  view plain  copy
  1. <?xml version="1.0"encoding='UTF-8'?>   
  2. <!DOCTYPE hibernate-mapping PUBLIC   
  3.                             "-//Hibernate/HibernateMapping DTD 3.0//EN"   
  4.                            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">   
  5.    
  6. <hibernate-mappingpackagehibernate-mappingpackage="com.blog.beans">   
  7.    <class name="User" table="user">   
  8.        <id name="id" column="id">   
  9.             <generatorclassgeneratorclass="native"></generator>   
  10.        </id>   
  11.        <property name="username" column="username"type="java.lang.String"  />  
  12.        <property name="password" column="password"type="java.lang.String"  />  
  13.    </class>   
  14. </hibernate-mapping>   
  15.    

④   TestAction内容更改如下:

[java]  view plain  copy
  1. package com.blog.action;  
  2. import java.util.Date;  
  3. import org.hibernate.HibernateException;  
  4. import org.hibernate.Session;  
  5. import org.hibernate.SessionFactory;  
  6. import org.hibernate.Transaction;  
  7. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;  
  8. importorg.hibernate.boot.registry.internal.StandardServiceRegistryImpl;  
  9. import org.hibernate.cfg.Configuration;  
  10. importorg.hibernate.service.ServiceRegistry;  
  11. import com.blog.beans.User;  
  12. import com.blog.dao.BaseDao;  
  13. import com.blog.daoImpl.UserDao;  
  14. importcom.opensymphony.xwork2.ActionSupport;  
  15. import sun.security.timestamp.TSRequest;  
  16. public class TestAction extendsActionSupport{  
  17.        privateDate date;  
  18.        privatestatic Configuration configuration = null;  
  19.        privatestatic SessionFactory sessionFactory = null;  
  20.        privatestatic ServiceRegistry serviceRegistry = null;  
  21.        publicvoid setDate(Date date){  
  22.               this.date=date;  
  23.        }  
  24.        publicDate getDate(){  
  25.               returndate;  
  26.        }  
  27.        publicString execute() throws Exception{  
  28.               System.out.println("Struts2测试成功!!");  
  29.               System.out.println("Spring测试:目前时间是:"+date);  
  30.                try {  
  31.                       Configuration configuration = newConfiguration().configure();  
  32.                      //以下这两句是4.3的新用法  
  33.                      StandardServiceRegistryBuilderbuilder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());  
  34.                      StandardServiceRegistryImplregistry = (StandardServiceRegistryImpl) builder.build();  
  35.                      SessionFactorysessionFactory = configuration.buildSessionFactory(registry);  
  36.                      Sessionsession = sessionFactory.openSession();  
  37.                      Transactiontx = session.beginTransaction();  
  38.                      Useruser=new User();  
  39.                      //user.setId(1);  
  40.                      user.setUsername("MK");  
  41.                      user.setPassword("123456");  
  42.                      BaseDaodao=new UserDao();  
  43.                      dao.setSession(session);  
  44.                      dao.saveObject(user);  
  45.                      tx.commit();  
  46.                      session.close();  
  47.                       } catch (HibernateException e) {  
  48.                        e.printStackTrace();  
  49.                       }  
  50.               return"success";  
  51.        }  
  52. }  


总结:

到这里已经完成了Hibernate框架的搭建。Hibernate的思路如下,使用一个bean类,将java的基本数据与数据库中表的数据一一对应起来,比如这里的User类,属性中有id,username,password,分别对应数据表中的id,username和password,他们是一一对应的关系。并且在这里所有的属性都要设置set和get方法。那么hibernate框架通过什么来完成这种转换呢?在这里便是通过user.hbm.xml来实现。

[html]  view plain  copy
  1. <class name="User" table="user">   
  2.     <id name="id" column="id">   
  3.          <generatorclassgeneratorclass="native"></generator>   
  4.     </id>   
  5.     <property name="username" column="username"type="java.lang.String"  />  
  6.     <property name="password" column="password"type="java.lang.String"  />  
  7. </class>   

name对应java中的字段,column对应数据库中的字段,通过这样的配置。Hibernate配置文件hibernate.cfg.xml中配置了账号,密码,数据库方言之类的数据库基本信息,同时通过<mapping resource="User.hbm.xml"/>来指定映射文件,即我们前面说的user与数据库中user表之间的映射关系通过User.hbm.xml就可以找到。


 

第五步:完成Hibernate与Spring框架的整合。

①   在applicationContext.xml中配置dataSource、sessionFactory、transactionManager。

[html]  view plain  copy
  1. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">   
  2.            <property name="driverClass" value="com.mysql.jdbc.Driver"/>   
  3.            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mankind"/>   
  4.            <property name="user" value="root"/>   
  5.            <property name="password" value="123456"/>   
  6.               </bean>   
  7.               <beanidbeanid="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">   
  8.                    <property name="dataSource" ref="dataSource"/>   
  9.                    <property name="configLocation"value="classpath:hibernate.cfg.xml" /> <!-- 加载hibernate配置文件 -->   
  10.               </bean>   
  11.         <bean id="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager">   
  12.                  <property name="sessionFactory"ref="sessionFactory" />   
  13.               </bean>   
  14.               <tx:adviceidtx:adviceid="advice" transaction-manager="transactionManager">   
  15.                   <tx:attributes>   
  16.                       <tx:method name="save*" propagation="REQUIRED"/>   
  17.                       <tx:method name="update*" propagation="REQUIRED"/>   
  18.                       <tx:method name="delete*" propagation="REQUIRED"/>   
  19.                       <tx:method name="*" propagation="SUPPORTS"/>   
  20.                   </tx:attributes>   
  21.               </tx:advice>   
  22.               <aop:config>   
  23.            <!-- 配置哪些包的类要切入事务 -->   
  24.            <aop:pointcut id="pointcut" expression="execution(*com.blog.daoImpl.*.*(..))" />   
  25.            <aop:advisor advice-ref="advice"pointcut-ref="pointcut"/><!-- 连接了上面的advice和上面的pointcut -->   
  26.            <!-- aop:pointcut要写在aop:advisor上面,否则会报错 -->   
  27.         </aop:config>  


②   由于在applicationContext.xml中配置了DataSource,可以删除hibernate.cfg.xml中相对应的四项(driverClass,jdbcURL,user,password)。其余的不用删,因为我们在spring中引用了hibernate.cfg.xml。

③   修改BaseDao

[java]  view plain  copy
  1. public interface BaseDao {   
  2.     publicvoid saveObject(Object obj) throws HibernateException;   
  3. }   

④   修改UserDao

[java]  view plain  copy
  1. public class UserDao implements BaseDao {  
  2.        privateSessionFactory sessionFactory;  
  3.         //当需要使用sessoinFactory的时候,Spring会将sessionFactory注入进来   
  4.     publicvoid setSessionFactory(SessionFactory sessionFactory) {   
  5.        this.sessionFactory = sessionFactory;   
  6.     }     
  7.     protectedSession getSession() {   
  8.        //从当前线程获取session,如果没有则创建一个新的session   
  9.        return sessionFactory.getCurrentSession();   
  10.     }   
  11.     publicvoid saveObject(Object obj) throws HibernateException {   
  12.        getSession().save(obj);  
  13.     }  
  14. }  

⑤   修改TestAction

[java]  view plain  copy
  1. public class TestAction extends ActionSupport{  
  2.        privateDate date;  
  3.        privateBaseDao userDao;  
  4.        publicvoid setDate(Date date){  
  5.               this.date=date;  
  6.        }  
  7.        publicDate getDate(){  
  8.               returndate;  
  9.        }  
  10.        publicvoid setUserDao(BaseDao userDao){  
  11.               this.userDao=userDao;  
  12.        }  
  13.        publicBaseDao getUserDao(){  
  14.               returnuserDao;  
  15.        }  
  16.        publicString execute() throws Exception{  
  17.               System.out.println("Struts2测试成功!!");  
  18.               System.out.println("Spring测试:目前时间是:"+date);  
  19.                try {  
  20.                      Useruser=new User();  
  21.                      user.setUsername("MK");  
  22.                      user.setPassword("123456");  
  23.                      userDao.saveObject(user);  
  24.                       } catch (HibernateException e) {  
  25.                        e.printStackTrace();  
  26.                       }  
  27.               return"success";  
  28.        }  

⑥   修改applicationContext.xml,依赖注入TestAction和UserDao

[html]  view plain  copy
  1. <bean id="userDao" class="com.blog.daoImpl.UserDao">   
  2.            <property name="sessionFactory"ref="sessionFactory" />   
  3. </bean>   
  4. <bean id="date" class="java.util.Date"/>  
  5. <bean id="TestAction" class="com.blog.action.TestAction"scope="prototype">   
  6.          <property name="date" ref="date"/>  
  7.          <property name="userDao" ref="userDao"/>  
  8. </bean>  


总结:

很明显,在Hibernate和Spring整合之前,我们在TestAction中需要写很长很长的代码来获得Session,整合之后,代码量大大减少。需要注意的地方是,Spring是针对接口来编程的,在TestAactoin中,userDao不能声明为userDao类型,而是应该声明为它的接口BaseDao,否则会报错。这个坑了我几个小时的时间..

框架到这里就差不多都打通了,剩下的地方再根据需要改一改就可以开始开发了。




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

本项目下载地址:

github:https://github.com/SCAUMankind/SSHBlogSystem

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值