zoukankan      html  css  js  c++  java
  • Spring Security3实现

    采用Maven管理,Spring Mvc Jpa等技术

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.wiker</groupId>
        <artifactId>springSecurity</artifactId>
        <packaging>war</packaging>
        <version>0.0.1-SNAPSHOT</version>
        <name>springSecurity Maven Webapp</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <!-- 主要依赖库的版本定义 -->
            <c3p0.version>0.9.1.2</c3p0.version>
            <spring-hibernate3.version>2.0.8</spring-hibernate3.version>
            <javax.transaction.version>1.1</javax.transaction.version>
            <org.kohsuke.stapler.version>2.1-rev6</org.kohsuke.stapler.version>
            <spring-web.version>3.2.3.RELEASE</spring-web.version>
            <commons-lang.version>2.5</commons-lang.version>
            <javax.xml.rpc.version>1.1</javax.xml.rpc.version>
            <commons-email.version>1.1</commons-email.version>
            <org.apache.axis.version>1.4</org.apache.axis.version>
            <commons-fileupload.version>1.3</commons-fileupload.version>
            <jdom.version>1.1</jdom.version>
            <javax.servlet.jstl.version>1.2</javax.servlet.jstl.version>
            <javax.servlet.api.version>2.5</javax.servlet.api.version>
            <jxl.version>2.6.12</jxl.version>
            <javax.activation.version>1.1.1</javax.activation.version>
            <javax.mail.version>1.4.5</javax.mail.version>
            <spring.version>3.2.3.RELEASE</spring.version>
            <hibernate.version>4.1.8.Final</hibernate.version>
            <hibernate.core.version>4.1.8.Final</hibernate.core.version>
            <spring-data-jpa.version>1.2.0.RELEASE</spring-data-jpa.version>
            <commons-dbcp.version>1.4</commons-dbcp.version>
            <sitemesh.version>2.4.2</sitemesh.version>
            <hibernate-validator.version>4.3.0.Final</hibernate-validator.version>
            <jackson.version>2.1.2</jackson.version>
            <jackson-asl.version>1.9.5</jackson-asl.version>
            <slf4j.version>1.7.2</slf4j.version>
            <log4j.version>1.2.17</log4j.version>
            <commons-lang3.version>3.1</commons-lang3.version>
            <guava.version>13.0.1</guava.version>
            <quartz.version>1.5.2</quartz.version>
            <freemarker.version>2.3.19</freemarker.version>
            <httpclient.version>4.2.2</httpclient.version>
            <commons-httpclient.version>3.0.1</commons-httpclient.version>
            <joda-time.version>2.1</joda-time.version>
            <junit.version>4.11</junit.version>
            <testng.version>6.3</testng.version>
            <mockito.version>1.9.5</mockito.version>
            <selenium.version>2.28.0</selenium.version>
            <jetty.version>7.6.8.v20121106</jetty.version>
            <h2.version>1.3.170</h2.version>
            <codec.version>1.6</codec.version>
            <dom4j.version>1.6.1</dom4j.version>
            <lombok.version>0.11.0</lombok.version>
            <wro4j.version>1.4.7</wro4j.version>
            <wro4j.extensions.version>1.4.7</wro4j.extensions.version>
            <commons-io.version>2.4</commons-io.version>
            <commons-collections.version>3.2.1</commons-collections.version>
            <gson.version>2.2.2</gson.version>
            <pinyin4j.version>2.5.0</pinyin4j.version>
            <wicked-charts.version>1.4.3</wicked-charts.version>
            <batik-all.version>1.8pre-r1084380</batik-all.version>
            <rhino.version>1.7R4</rhino.version>
            <thumbnailator.version>[0.4, 0.5)</thumbnailator.version>
            <struts2.core.version>2.3.14.3</struts2.core.version>
            <wsdl4j.version>1.5.1</wsdl4j.version>
            <aspectjrt.version>1.7.1</aspectjrt.version>
            <velocity.version>1.7</velocity.version>
            <antlr.version>2.7.6</antlr.version>
            <jchardet.version>1.0</jchardet.version>
            <google-collection.version>1.0</google-collection.version>
            <json-lib.version>2.4</json-lib.version>
            <urlrewritefilter.version>4.0.3</urlrewritefilter.version>
    
            <!-- Plugin的属性定义 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <jdk.version>1.6</jdk.version>
    
            <server.url>http://localhost:8080/manager/html</server.url>
            <server.user>admin</server.user>
            <server.password>admin</server.password>
    
            <jdbc.driver.groupId>mysql</jdbc.driver.groupId>
            <jdbc.driver.artifactId>mysql-connector-java</jdbc.driver.artifactId>
            <jdbc.driver.version>5.1.21</jdbc.driver.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.google.collections</groupId>
                <artifactId>google-collections</artifactId>
                <version>${google-collection.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- <dependency> <groupId>org.apache.axis2</groupId> <artifactId>axis2</artifactId> 
                <version>${org.apache.axis2.version}</version> </dependency> -->
            <dependency>
                <groupId>org.apache.axis</groupId>
                <artifactId>axis</artifactId>
                <version>${org.apache.axis.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>${commons-lang.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <!-- Spring Security -->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-core</artifactId>
                <version>3.1.4.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.18</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-web</artifactId>
                <version>3.1.4.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
                <version>3.1.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectjrt.version}</version>
            </dependency>
            <dependency>
                <groupId>wsdl4j</groupId>
                <artifactId>wsdl4j-qname</artifactId>
                <version>${wsdl4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>${aspectjrt.version}</version>
            </dependency>
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2.2</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>asm</groupId>
                <artifactId>asm</artifactId>
                <version>3.3.1</version>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>${hibernate.version}</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
                <version>${hibernate.core.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.xml.rpc</groupId>
                <artifactId>javax.xml.rpc-api</artifactId>
                <version>${javax.xml.rpc.version}</version>
            </dependency>
            <!-- spring data access -->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-jpa</artifactId>
                <version>${spring-data-jpa.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>junit</groupId>
                        <artifactId>junit-dep</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>net.sf.json-lib</groupId>
                <artifactId>json-lib</artifactId>
                <version>${json-lib.version}</version>
                <classifier>jdk15</classifier>
            </dependency>
            <dependency>
                <groupId>org.tuckey</groupId>
                <artifactId>urlrewritefilter</artifactId>
                <version>${urlrewritefilter.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>javax.annotation-api</artifactId>
                <version>1.2</version>
            </dependency>
    
            <!-- dbcp connection pool -->
            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
                <version>${commons-dbcp.version}</version>
                <scope>runtime</scope>
            </dependency>
    
            <!-- PERSISTENCE end -->
            <!-- WEB begin -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>jdom</groupId>
                <artifactId>jdom</artifactId>
                <version>${jdom.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>${javax.servlet.jstl.version}</version>
            </dependency>
            <dependency>
                <groupId>net.sourceforge.jexcelapi</groupId>
                <artifactId>jxl</artifactId>
                <version>${jxl.version}</version>
            </dependency>
    
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>${javax.servlet.api.version}</version>
                <scope>provided</scope>
            </dependency>
            <!-- JSR303 BeanValidator -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>${hibernate-validator.version}</version>
            </dependency>
            <!-- pinyin4j begin -->
            <!-- <dependency> <groupId>pinyin4j</groupId> <artifactId>pinyin4j</artifactId> 
                <version>${pinyin4j.version}</version> </dependency> -->
            <!-- pinyin4j end -->
            <!-- JSON begin -->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.module</groupId>
                <artifactId>jackson-module-jaxb-annotations</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-xml</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-core-asl</artifactId>
                <version>${jackson-asl.version}</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-mapper-asl</artifactId>
                <version>${jackson-asl.version}</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-jaxrs</artifactId>
                <version>${jackson-asl.version}</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-xc</artifactId>
                <version>${jackson-asl.version}</version>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>${gson.version}</version>
            </dependency>
            <dependency>
                <groupId>quartz</groupId>
                <artifactId>quartz</artifactId>
                <version>${quartz.version}</version>
            </dependency>
            <!-- JSON end -->
    
            <!-- LOGGING begin -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>${slf4j.version}</version>
                <scope>runtime</scope>
            </dependency>
            <!-- common-logging 实际调用slf4j -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>${slf4j.version}</version>
                <scope>runtime</scope>
            </dependency>
            <!-- java.util.logging 实际调用slf4j -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jul-to-slf4j</artifactId>
                <version>${slf4j.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.lazyluke</groupId>
                <artifactId>log4jdbc-remix</artifactId>
                <version>0.2.7</version>
                <scope>runtime</scope>
            </dependency>
            <!-- LOGGING end -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>
            <dependency>
                <groupId>org.kohsuke.stapler</groupId>
                <artifactId>json-lib</artifactId>
                <version>${org.kohsuke.stapler.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring-web.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-hibernate3</artifactId>
                <version>${spring-hibernate3.version}</version>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>${guava.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>${codec.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons-io.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>${commons-collections.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>${commons-fileupload.version}</version>
            </dependency>
            <!-- GENERAL UTILS end -->
    
            <!-- OTHER TOOLS begin -->
            <!-- httpclient -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>${httpclient.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>commons-logging</groupId>
                        <artifactId>commons-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-httpclient</groupId>
                <artifactId>commons-httpclient</artifactId>
                <version>${commons-httpclient.version}</version>
            </dependency>
    
            <!-- template engine -->
            <!-- <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> 
                <version>${freemarker.version}</version> </dependency> -->
    
            <!-- third party dependencies -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>${dom4j.version}</version>
            </dependency>
    
            <!-- email -->
            <dependency>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
                <version>${javax.mail.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-email</groupId>
                <artifactId>commons-email</artifactId>
                <version>${commons-email.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>${javax.activation.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.transaction</groupId>
                <artifactId>jta</artifactId>
                <version>${javax.transaction.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity</artifactId>
                <version>${velocity.version}</version>
            </dependency>
            <dependency>
                <groupId>c3p0</groupId>
                <artifactId>c3p0</artifactId>
                <version>${c3p0.version}</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>${mockito.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-all</artifactId>
                <version>${mockito.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${spring.version}</version>
                <scope>test</scope>
            </dependency>
            <!-- h2 -->
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <version>${h2.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>antlr</groupId>
                <artifactId>antlr</artifactId>
                <version>${antlr.version}</version>
            </dependency>
            <dependency>
                <groupId>net.sourceforge.jchardet</groupId>
                <artifactId>jchardet</artifactId>
                <version>${jchardet.version}</version>
            </dependency>
            <dependency>
                <groupId>xml-apis</groupId>
                <artifactId>xml-apis</artifactId>
                <version>1.4.01</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-taglibs</artifactId>
                <version>3.1.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.9</version>
                <exclusions>
                    <exclusion>
                        <artifactId>xml-apis</artifactId>
                        <groupId>xml-apis</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
        <build>
            <finalName>springSecurity</finalName>
            <plugins>
    
                <plugin>
                    <groupId>org.mortbay.jetty</groupId>
                    <artifactId>maven-jetty-plugin</artifactId>
                    <configuration>
                        <scanIntervalSeconds>10</scanIntervalSeconds>
                        <webAppConfig>
                            <contextPath>/springSecurity</contextPath>
                        </webAppConfig>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

    applicationContext-dao.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"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
        default-lazy-init="true">
    
        <description>Spring DAO Configration</description>
    
    
        <!-- Spring Data Jpa配置 -->
        <jpa:repositories base-package="com.wiker"
            transaction-manager-ref="transactionManager"
            entity-manager-factory-ref="entityManagerFactory" />
    
        <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <!-- Connection Info -->
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/test" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </bean>
    
        <!-- 利用Spring的实体管理器工厂来创建JPA实体管理器 -->
        <bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan">
                <list>
                    <value>com.wiker</value>
                </list>
            </property>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="database" value="MYSQL" />
                    <property name="showSql" value="true" />
                    <property name="generateDdl" value="true" />
                </bean>
            </property>
        </bean>
    
        <context:component-scan base-package="com.wiker"></context:component-scan>
    
        <context:annotation-config />
    
        <!-- Jpa 事务配置 -->
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>
    
        <!-- 使用annotation定义事务 -->
        <tx:annotation-driven transaction-manager="transactionManager"
            proxy-target-class="true" />
    
    
    
    </beans>

    applicationContext-service.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"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
        default-lazy-init="true">
    
        <description>Spring Service Configration</description>
    
        <!-- scan service class with @components -->
        <context:component-scan base-package="com.wiker.security.service" />
    
        <bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:application.properties</value>
                </list>
            </property>
        </bean>
    
        <!-- <bean name="propertyLoader"
            class="com.urbanmania.spring.beans.factory.config.annotations.PropertyFileLoader">
            <property name="resources">
                <value>classpath:application.properties</value>
            </property>
        </bean>
    
        <bean
            class="com.urbanmania.spring.beans.factory.config.annotations.PropertyAnnotationAndPlaceholderConfigurer">
            <property name="propertyLoaders">
                <ref bean="propertyLoader" />
            </property>
        </bean> -->
    </beans>

    spring-security.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:security="http://www.springframework.org/schema/security"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/security 
                http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    
        <!-- 启用注解方式对方法的权限控制 -->
        <security:global-method-security
            pre-post-annotations="enabled" secured-annotations="enabled"
            jsr250-annotations="enabled" proxy-target-class="true">
            <!-- <security:protect-pointcut access="VIP"
                expression="execution(* com.zf.service.VipService.*(..))" /> -->
        </security:global-method-security>
    
        <!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面 -->
        <security:http use-expressions="true" access-denied-page="/powermiss.jsp" entry-point-ref="authenticationProcessingFilterEntryPoint">
            <!-- 对登录页面,所有的用户都可以访问 -->
            <security:intercept-url pattern="/login.jsp*"
                access="permitAll" />
            <security:intercept-url pattern="/index.jsp*"
                access="permitAll" />
            <!-- <security:intercept-url pattern="/vip.jsp*"
                access="hasRole('VIP')" />
            <security:intercept-url pattern="/admin.jsp*"
                access="hasRole('ADMIN')" />
            对所有的资源,都必须要有COMM权限 才可以访问  
            <security:intercept-url pattern="/*"
                access="hasRole('COMM')" /> -->
                
            <!-- 使用自己的过滤器 -->
            <!-- 下面的配置表示将自己的过滤器放在FORM_LOGIN_FILTER过滤链的最前面(可以这样来验证登录验证码) -->
            <security:custom-filter
                ref="validateCodeAuthenticationFilter"  position="FORM_LOGIN_FILTER"
                 />
                
            <!-- 配置登录页面为login.jsp ,登录成功默认跳转到index.jsp,登录失败返回login.jsp并携带参数error=true -->
    <!--         <security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" />  -->
            
            <!-- 退出配置 -->
            <security:logout invalidate-session="true"
                logout-success-url="/login.jsp" logout-url="/auth/logout" />
    
        </security:http>
        
        
        <bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <property name="loginFormUrl" value="/login.jsp"></property>
        </bean>
    
        <!-- 验证码过滤器 -->
        <bean id="validateCodeAuthenticationFilter"
            class="com.wiker.security.controller.VolidateAuthCodeUsernamePasswordAuthenticationFilter">
            <property name="authenticationSuccessHandler"
                ref="loginLogAuthenticationSuccessHandler"></property>
            <property name="authenticationFailureHandler"
                ref="simpleUrlAuthenticationFailureHandler"></property>
            <property name="authenticationManager" ref="authenticationManager"></property>
        </bean>
    
        <!-- 登录成功 -->
        <bean id="loginLogAuthenticationSuccessHandler"
            class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
            <property name="defaultTargetUrl" value="/index.jsp"></property>
        </bean>
    
        <!-- 登录失败 -->
        <bean id="simpleUrlAuthenticationFailureHandler"
            class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <property name="defaultFailureUrl" value="/login.jsp?error=true"></property>
        </bean>
    
    
        <!-- 配置一个认证管理器 -->
        <security:authentication-manager alias="authenticationManager">
            <!-- 使用自定义的UserDetailService -->
            <security:authentication-provider
                user-service-ref="accountService">
                <!-- 下面的内容就可注释掉了 -->
                <!-- <security:user-service> -->
                <!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
                <!-- <security:user name="admin" password="admin" authorities="ROLE_USER"/> -->
                <!-- </security:user-service> -->
            </security:authentication-provider>
        </security:authentication-manager>
    
    
    </beans>

    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"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
        <!-- 自动扫描且只扫描@Controller -->
        <context:component-scan base-package="com.wiker.security.controller"
            use-default-filters="false">
            <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Controller" />
        </context:component-scan>
    
        <!-- Application Message Bundle -->
        <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
            <property name="basename" value="messages" />
        </bean>
    
        <!-- Json返回 乱码处理 -->
        <bean
            class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <list>
                    <bean
                        class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
                    <bean
                        class="org.springframework.http.converter.StringHttpMessageConverter">
                        <property name="supportedMediaTypes">
                            <list>
                                <value>text/plain;charset=UTF-8</value>
                            </list>
                        </property>
                    </bean>
                    <bean
                        class="org.springframework.http.converter.ResourceHttpMessageConverter" />
                    <bean
                        class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
                    <bean
                        class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" />
                    <bean
                        class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
                </list>
            </property>
        </bean>
    
    
        <mvc:annotation-driven />
    
        <!-- 将无法mapping到Controller的path交给default servlet handler处理 -->
        <mvc:default-servlet-handler />
    
        <!-- 定义JSP文件的位置 -->
        <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/" />
            <property name="suffix" value=".jsp" />
        </bean>
    
        <!-- Configure the multipart resolver for uploading -->
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
    
    
        
    </beans>

    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/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        <context-param>
            <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
            <param-value>messages</param-value>
        </context-param>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath*:/applicationContext-dao.xml,
                classpath*:/applicationContext-service.xml,
                classpath*:/spring-security.xml
            </param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <filter>
            <filter-name>encodingFilter</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>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <servlet>
            <servlet-name>springServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet>
            <servlet-name>CaptchaServlet</servlet-name>
            <servlet-class> 
                com.wiker.security.controller.CaptchaServlet
               </servlet-class>
          </servlet>
          <servlet-mapping>
            <servlet-name>CaptchaServlet</servlet-name>
            <url-pattern>/captchaServlet</url-pattern>
          </servlet-mapping>
        <servlet-mapping>
            <servlet-name>springServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <!-- spring security -->  
        <filter>  
            <filter-name>springSecurityFilterChain</filter-name>  
            <filter-class>  
                org.springframework.web.filter.DelegatingFilterProxy  
            </filter-class>  
        </filter>  
          
        <filter-mapping>  
            <filter-name>springSecurityFilterChain</filter-name>  
            <url-pattern>/*</url-pattern>  
        </filter-mapping>  
    
    
    
    </web-app>

    index.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
           
      <body>       
              <h3>登录成功,欢迎您:<sec:authentication property="name" /></h3>      
              <a href="<%=basePath%>admin.jsp">进入管理员页面</a>
              <a href="<%=basePath%>vip.jsp">进入会员页面</a>
              <a href="<%=basePath%>auth/logout">注销</a>  
      </body>
    </html>

    index.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%
        String path = request.getContextPath();
        String basePath = request.getScheme() + "://" + request.getServerName() + ":"
                + request.getServerPort() + path + "/";
        
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    <style type="text/css"> 
    div.error { 
        width: 260px; 
        border: 2px solid red; 
        background-color: yellow; 
        text-align: center; 
    } 
    
    div.hide { 
        display: none; 
    } 
        </style> 
    </head>
    <body>
      <div class="error ${param.error == true ? '' : 'hide'}"> 
               登陆失败<br> 
        ${sessionScope['SPRING_SECURITY_LAST_EXCEPTION'].message} 
        </div> 
        <h3>用户登录</h3>
        <!-- from的action地址,以及用户名密码的name 。都是spring-security固定的。 -->
        <form action="<%=basePath%>j_spring_security_check" method="post">
    
            <p>
                <label for="j_username">Username</label> <input id="j_username"
                    name="j_username" type="text" />
            </p>
    
            <p>
                <label for="j_password">Password</label> <input id="j_password"
                    name="j_password" type="password" />
            </p>
            <p>
                <label for="j_password">验证码:</label> <input id="j_password"
                    name="code" type="password" /> <IMG style="CURSOR: pointer"
                    onclick="this.src='captchaServlet?t='+(new Date().getTime());"
                    alt="看不清楚?请点击刷新验证码!" align='absmiddle' src="captchaServlet"
                    height="18" width="55">
            </p>
            <p>
                <input type="checkbox" name="_spring_security_remember_me">两周之内不必登陆
            </p>
    
            <input type="submit" value="Login" />
    
        </form>
    
    </body>
    </html>

    powermiss.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'powermiss.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
    
      </head>
      
      <body>
          
          <h1 style="color: red;">对不起,您无权访问该资源!</h1>
          
      </body>
    </html>

    VolidateAuthCodeUsernamePasswordAuthenticationFilter.java

    package com.wiker.security.controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.apache.commons.lang.StringUtils;
    import org.springframework.security.authentication.AuthenticationServiceException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.util.TextEscapeUtils;
      
    /**
     * @author Wiker Yong Email:<a href="mailto:wikeryong@gmail.com">wikeryong@gmail.com</a>
     * @date 2013-7-15 下午5:56:54
     * @version 1.0-SNAPSHOT
     */
    public class VolidateAuthCodeUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{  
      
        private boolean postOnly = true;  
        private boolean allowEmptyValidateCode = false;  
        private String sessionvalidateCodeField = DEFAULT_SESSION_VALIDATE_CODE_FIELD;  
        private String validateCodeParameter = DEFAULT_VALIDATE_CODE_PARAMETER;  
        public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";  
        // session中保存的验证码  
        public static final String DEFAULT_SESSION_VALIDATE_CODE_FIELD = "rand";  
        // 输入的验证码  
        public static final String DEFAULT_VALIDATE_CODE_PARAMETER = "code";  
      
        @Override  
        public Authentication attemptAuthentication(HttpServletRequest request,  
                HttpServletResponse response) throws AuthenticationException {  
            if (postOnly && !request.getMethod().equals("POST")) {  
                throw new AuthenticationServiceException(  
                        "Authentication method not supported: "  
                                + request.getMethod());  
            }  
      
            String username = obtainUsername(request);  
            String password = obtainPassword(request);  
      
            if (username == null) {  
                username = "";  
            }  
      
            if (password == null) {  
                password = "";  
            }  
      
            username = username.trim();  
      
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(  
                    username, password);  
      
            // Place the last username attempted into HttpSession for views  
            HttpSession session = request.getSession(false);  
      
            if (session != null || getAllowSessionCreation()) {  
                request.getSession().setAttribute(  
                        SPRING_SECURITY_LAST_USERNAME_KEY,  
                        TextEscapeUtils.escapeEntities(username));  
            }  
      
            // Allow subclasses to set the "details" property  
            setDetails(request, authRequest);  
            // check validate code  
            if (!isAllowEmptyValidateCode())  
                checkValidateCode(request);  
            // 根据用户和密码查询  
             
            return this.getAuthenticationManager().authenticate(authRequest);  
        }  
      
        /** 
         *  
         * <li>比较session中的验证码和用户输入的验证码是否相等</li> 
         *  
         */  
        protected void checkValidateCode(HttpServletRequest request) {  
            String sessionValidateCode = obtainSessionValidateCode(request);  
            String validateCodeParameter = obtainValidateCodeParameter(request);  
            if (StringUtils.isEmpty(validateCodeParameter)  
                    || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {  
                throw new AuthenticationServiceException("验证码错误!");  
            }  
        }  
      
        private String obtainValidateCodeParameter(HttpServletRequest request) {  
            return request.getParameter(validateCodeParameter);  
        }  
      
        protected String obtainSessionValidateCode(HttpServletRequest request) {  
            Object obj = request.getSession()  
                    .getAttribute(sessionvalidateCodeField);  
            return null == obj ? "" : obj.toString();  
        }  
      
        public boolean isPostOnly() {  
            return postOnly;  
        }  
      
        @Override  
        public void setPostOnly(boolean postOnly) {  
            this.postOnly = postOnly;  
        }  
      
        public String getValidateCodeName() {  
            return sessionvalidateCodeField;  
        }  
      
        public void setValidateCodeName(String validateCodeName) {  
            this.sessionvalidateCodeField = validateCodeName;  
        }  
      
        public boolean isAllowEmptyValidateCode() {  
            return allowEmptyValidateCode;  
        }  
      
        public void setAllowEmptyValidateCode(boolean allowEmptyValidateCode) {  
            this.allowEmptyValidateCode = allowEmptyValidateCode;  
        }  
      
    } 

    User.java

    package com.wiker.security.dao.entity;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.Table;
    
    /** 
     * 用户Bean
     * @author WikerYong  <a>Email:yw_312@foxmail.com<a/>
     * @version 2011-11-9 上午10:03:18
     */
    @Entity
    @Table(name = "user")
    public class User implements Serializable{
        
        protected static final long serialVersionUID = -5204668503508016656L;
        
        @Id  
        @GeneratedValue(strategy = GenerationType.AUTO)  
        protected Long id;
        protected String username;
        protected String password;
        @ManyToMany  
        @JoinTable(name="user_role" , joinColumns = {  
                @JoinColumn(name = "userid")  
        }, inverseJoinColumns = {@JoinColumn(name="roleid")})   
        private List<Role> roles = new ArrayList<Role>();
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public List<Role> getRoles() {
            return roles;
        }
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }  
    }

    UserDao.java

    package com.wiker.security.dao.repository;
    
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.repository.PagingAndSortingRepository;
    
    import com.wiker.security.dao.entity.User;
    
    
    
    /**
     * @author Wiker Yong Email:<a href="mailto:wikeryong@gmail.com">wikeryong@gmail.com</a>
     * @date 2013-6-19 上午11:11:52
     * @version 1.0-SNAPSHOT
     */
    public interface UserDao extends PagingAndSortingRepository<User,Long>,JpaSpecificationExecutor<User> {
        
        User findByUsernameAndPassword(String username,String password);
        
        User findByUsername(String username);
    
    }

    AccountService.java

    package com.wiker.security.service;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.GrantedAuthorityImpl;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    import com.wiker.security.dao.entity.User;
    import com.wiker.security.dao.repository.UserDao;
    
    
    @Service
    public class AccountService
            implements UserDetailsService {
        
        @Autowired
        private UserDao userDao;
        
        public UserDetails loadUserByUsername(String username)
                throws UsernameNotFoundException {
            User user = userDao.findByUsername(username);
            UserDetails userDetail = null;
            if (user != null) {
                userDetail = new org.springframework.security.core.userdetails.User(username,
                        user.getPassword(), true, true, true, true, findUserAuthorities(user));
            }
            
            return userDetail;
        }
        
        /**
         * 获取用户的权限
         * 
         * @param user
         * @return
         */
        @SuppressWarnings("deprecation")
        public Collection<GrantedAuthority> findUserAuthorities(User user) {
            List<GrantedAuthority> autthorities = new ArrayList<GrantedAuthority>();
            /*List<Role> roles = user.getRoles();
            for (Role Role : roles) {
                autthorities.add(new GrantedAuthorityImpl(Role.getRoleCode()));
            }*/
            autthorities.add(new GrantedAuthorityImpl("admin"));
            return autthorities;
        }
        
    }
  • 相关阅读:
    RabbitMq学习4-发布/订阅(Publish/Subscribe)
    RabbitMq学习3-工作队列(Work queues)
    《大型网站技术架构》-读书笔记七:安全架构
    RabbitMq学习2-php命令行模式测试rabbitmq
    《大型网站技术架构》-读书笔记六:可扩展架构
    RabbitMq学习1-介绍、安装和配置
    《大型网站技术架构》-读书笔记五:伸缩性架构
    C#构建树形数据结构
    数据结构和算法(一)概念
    C# 简介
  • 原文地址:https://www.cnblogs.com/wiker/p/3194316.html
Copyright © 2011-2022 走看看