zoukankan      html  css  js  c++  java
  • Java-Security(一):初体验

    Spring Security的前身是Acegi,在被收纳为Spring子项目后正式更改名为 Spring Security。本博客基于Spring Security的版本是 5.2.0.RELEASE。

    Spring Security 5.2.0.RELEASE 支持原声的OAuth2框架,支持更现在化的密码加密方式。

    Spring Security支持广泛的认证技术,这些技术大多由三方或相关标准组织开发。Spring Security已经集成的认证技术支持如下:

    •     HTTP BASIC authentication headers (一个基于IETF RFC的标准)
    •     HTTP Digest authentication headers (一个基于IETF RFC的标准)
    •     HTTP X.509 client certificate exchange (一个基于IETF RFC的标准)
    •     LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境)
    •     Form-based authentication (提供简单用户接口的需求)
    •     OpenID authentication(一种去中心化的身份认证方式)
    •     Authentication based on pre-established request headers(基于预先建立的请求头进行认证):(比如Computer Associates Siteminder,一种用户身份验证及授权的集中式安全基础方案)
    •     JA-SIG Central Authentication Service (也被称为CAS,这是一个流行的开源单点登录系统)
    •     Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (一个Spring远程调用协议)
    •     Automatic “remember-me” authentication (这样你可以设置一段时间,避免在一段时间内还需要重新验证)
    •     Anonymous authentication (允许未认证的任何调用,自动假设一个特定的安全主体)
    •     Run-as authentication (这在一个会话内使用不同安全身份的时候是非常有用的)
    •     Java Authentication and Authorization Service (JAAS,java验证和授权API)
    •     Java EE container authentication:允许系统继续使用容器管理这种身份验证方式
    •     Kerberos:一种使用对称秘钥机制,允许客户端与服务器相互确认身份和认证协议。

    除此之外,Spring Security还引入了一些第三方包,用于支持更多认证技术,比如:JOSSO等。如果这些技术都无法满足需求,则Spring Security允许我们编程写自己的认证技术。

    因此,在大部分情况下,当我们有java应用安全方面需求时,选择Spring Security往往是正确的而有效的。

    在授权上,Spring Security 不仅支持基于URL对Web的请求授权,还支持方法访问授权、对象访问授权等,基本涵盖了常见的大部分授权场景。

    新建Spring Security Maven项目

    1)新建spring-security-01 maven 项目

    pom.xml如下:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <springframework.version>5.2.0.RELEASE</springframework.version>
        <com.alibaba.version>1.1.21</com.alibaba.version>
        <mysql.version>8.0.11</mysql.version>
        <org.mybatis.version>3.4.6</org.mybatis.version>
        <org.mybatis.spring.version>2.0.3</org.mybatis.spring.version>
        <org.aspectj.version>1.9.4</org.aspectj.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${springframework.version}</version>
        </dependency>
    
        <!--AOP aspectjweaver 支持 -->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>${org.aspectj.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>${org.aspectj.version}</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-core</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-config</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-web</artifactId>
          <version>${springframework.version}</version>
        </dependency>
    
        <!--访问RDBMS-MySQL依赖 -->
        <!--MyBatis -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>${org.mybatis.version}</version>
        </dependency>
        <!-- Mybatis自身实现的Spring整合依赖 -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>${org.mybatis.spring.version}</version>
        </dependency>
    
        <!--MySql数据库驱动 -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>${com.alibaba.version}</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>${mysql.version}</version>
        </dependency>
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.13</version>
        </dependency>
    
        <!--form 设置为enctype="multipart/form-data",多文件上传,在applicationContext.xml中配置了bean
                multipartResolver时,需要依赖该包。 -->
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.4</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
          <groupId>commons-lang</groupId>
          <artifactId>commons-lang</artifactId>
          <version>2.6</version>
        </dependency>
    
        <!-- 编译依赖 -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
        </dependency>
        <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
    
        <!--日志支持 -->
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.26</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.26</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
    
        <!-- redis依赖包 -->
        <dependency>
          <groupId>redis.clients</groupId>
          <artifactId>jedis</artifactId>
          <version>3.1.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
        <dependency>
          <groupId>org.springframework.data</groupId>
          <artifactId>spring-data-redis</artifactId>
          <version>2.2.3.RELEASE</version>
        </dependency>
    
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    View Code

    pom中引入部分包含:spring-framework,springmvc,spring-security,其他。

    2)编写web.xml等配置文件

    2.1)web.xml配置

    <!DOCTYPE web-app PUBLIC
            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
        <display-name>Archetype Created Web Application</display-name>
    
        <welcome-file-list>
            <welcome-file>/index</welcome-file>
        </welcome-file-list>
    
        <!--加载dao/service/一些共享组件-->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:applicationContext-base.xml,
                classpath:applicationContext-security.xml
            </param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <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>
    
        <filter>
            <filter-name>multipartFilter</filter-name>
            <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
            <init-param>
                <param-name>multipartResolverBeanName</param-name>
                <param-value>multipartResolver</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>multipartFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter>
            <filter-name>hiddenHttpMethodFilter</filter-name>
            <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
            <init-param>
                <param-name>methodParam</param-name>
                <param-value>_method</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>hiddenHttpMethodFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter>
            <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!--加载springmvc controller viewsolver 等-->
        <servlet>
            <servlet-name>spring-security-01</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-security-01-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>spring-security-01</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    View Code

    web.xml中需要引入filter( characterEncodingFilter 、hiddenHttpMethodFilter 、multipartFilter 、 springSecurityFilterChain):
        2.1.1)characterEncodingFilter:用来实现对请求内容进行encoding处理,防止乱码;
        2.1.2)hiddenHttpMethodFilter:用来在表单中添加hidden标签,value=put|delete,实现put、delete方式提交表单;
        2.1.3)multipartFilter:上传文件过滤器;
        2.1.4)springSecurityFilterChain:加入spring security拦截器,实现认证、授权拦截。

    2.2)监听器ContextLoaderListener

    用来初始化spring applicationContext,用来自动扫描dao、service组件,上创解析器组件,以及spring security组件集成;
    applicationContext-base.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="com.dx.test.security"/>
    
        <!--上传文件解析器-->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="utf-8"></property>
            <property name="maxUploadSize" value="10240000"></property>
        </bean>
    </beans>

    applicationContext-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.xsd
           http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
        <!--
        从Spring Security 3.1开始,可以使用多个http元素为不同的请求模式定义单独的安全过滤器链配置。
        -->
        <security:http pattern="/css/**" security="none"/>
    
        <security:http auto-config="true" use-expressions="false">
            <security:csrf disabled="false"/>
            <security:intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <security:intercept-url pattern="/index" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <security:intercept-url pattern="/**" access="ROLE_USER"/>
    
            <security:form-login default-target-url="/index" />
            <security:logout delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/logout" />
    
        </security:http>
    
        <security:authentication-manager>
            <security:authentication-provider>
                <security:user-service>
                    <!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
                    NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
                    in samples easier. Normally passwords should be hashed using BCrypt
                    -->
                    <security:user name="admin" password="{noop}adminpwd" authorities="ROLE_USER, ROLE_ADMIN"/>
                    <security:user name="user" password="{noop}userpwd" authorities="ROLE_USER"/>
                </security:user-service>
            </security:authentication-provider>
        </security:authentication-manager>
    
    </beans>

    或者 去掉security:前缀,将<security:http/> 简写为<http>的另外一种配置方式:

    <?xml version="1.0" encoding="UTF-8"?>
    <bean:beans xmlns:bean="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/security"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
        <http pattern="/css/**" security="none"/>
    
        <http auto-config="true" use-expressions="false">
            <csrf disabled="false"/>
            <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <intercept-url pattern="/index" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <intercept-url pattern="/**" access="ROLE_USER"/>
            <form-login default-target-url="/index" />
            <logout delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/logout" />
        </http>
    
        <authentication-manager>
            <authentication-provider>
                <user-service>
                    <user name="admin" password="{noop}adminpwd" authorities="ROLE_USER, ROLE_ADMIN"/>
                    <user name="user" password="{noop}userpwd" authorities="ROLE_USER"/>
                </user-service>
            </authentication-provider>
        </authentication-manager>
    </bean:beans>

    2.2.1)从Spring Security 3.1开始,可以使用多个http元素为不同的请求模式定义单独的安全过滤器链配置,详情从上边配置可见。
    2.2.2)form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性:
        1. login-page 自定义登录页url,默认为/login
        2. login-processing-url 登录请求拦截的url,也就是form表单提交时指定的action
        3. default-target-url 默认登录成功后跳转的url
        4. always-use-default-target 是否总是使用默认的登录成功后跳转url
        5. authentication-failure-url 登录失败后跳转的url
        6. username-parameter 用户名的请求字段 默认为userName
        7. password-parameter 密码的请求字段 默认为password
        8. authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
        9. authentication-success-forward-url 用于authentication-failure-handler-ref
        10. authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
        11. authentication-failure-forward-url 用于authentication-failure-handler-ref
        12. authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
    2.2.3)密码的前缀是{noop},以指示DelegatingPasswordEncoder应使用NoOpPasswordEncoder。这对生产是不安全的,但会使在demo中阅读更容易。通常密码应该使用BCrypt散列。

    2.3)sevlet实现类DispatcherServlet

    用来初始化springmvc系统,指定servlet实现类,加载springmvc的controller,view视图等;
    加载文件spring-security-01-servlet.xml中指定了:自动扫描controller包路径、自动扫描驱动包、开启aop、jsp视图解析器。

    <?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" xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 开启controller注解支持 -->
        <context:component-scan base-package="com.dx.test.controller" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
            <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
        </context:component-scan>
    
        <!-- 使用注解驱动:自动配置处理器映射器与处理器适配器 -->
        <mvc:annotation-driven></mvc:annotation-driven>
    
        <!-- 开启aop,对类代理 -->
        <aop:config proxy-target-class="true"></aop:config>
    
        <!-- 单独使用jsp视图解析器时,可以取消掉注释,同时注释掉:下边的‘配置多个视图解析’配置-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>

     添加views页面、controller控制类、测试项目

    1)添加views页面和controller类

    1)新建view页面webapp/WEB-INF/views/index.jsp

    <html>
    <body>
    <h2>Hello World!</h2>
    </body>
    </html>

    2)新建LoginController.java

    package com.dx.test.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Controller
    public class LoginController {
        @RequestMapping(value = "/login", method = RequestMethod.GET)
        public String loginPage(@RequestParam(value = "error", required = false) String error, Model model) {
            if (error != null) {
                return "login-failure";
            }
            return "login";
        }
    }

    3)新建IndexController.java

    package com.dx.test.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    public class IndexController {
        @RequestMapping(value = "/", method = RequestMethod.GET)
        public String home() {
            return "redirect:/index";
        }
    
        @RequestMapping(value = "/index", method = RequestMethod.GET)
        public String index() {
            return "/index";
        }
    }

    2)启动项目测试

    启动项目,自动跳转到http://localhost:8080/spring_security_01_war/下,此时允许访问,输入地址:http://localhost:8080/spring_security_01_war/index也是允许访问的,因为我们再applicationContext-security.xml中配置了'/'和‘/index’是允许任何人访问的,因此这里可以访问‘http://localhost:8080/spring_security_01_war/’和‘http://localhost:8080/spring_security_01_war/index’。

    访问'http://localhost:8080/spring_security_01_war/admin',此时会自动跳转到‘http://localhost:8080/spring_security_01_war/login’登录页面。

    从页面查看login页面html代码如下:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>Please sign in</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
        <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
      </head>
      <body>
         <div class="container">
          <form class="form-signin" method="post" action="/spring_security_01_war/login">
            <h2 class="form-signin-heading">Please sign in</h2>
            <p>
              <label for="username" class="sr-only">Username</label>
              <input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
            </p>
            <p>
              <label for="password" class="sr-only">Password</label>
              <input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
            </p>
    <input name="_csrf" type="hidden" value="a81e8a84-36e7-4594-806b-bb2f43f5013b" />
            <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
          </form>
    </div>
    </body></html>

    备注:

    1)上边页面是spring-security内部内置拦截未认证时,跳转的认证页面。

    2)其中配置信息对应的就是applicationContext-security.xml中配置的信息;

    3)"_crsf"标签取决于配置“<security:csrf disabled="false"/>”;如果不想启用就配置为“<security:csrf disabled="true"/>”,此时页面中也不会输出该标签。

    输入上边配置的内存账户、密码后,再次访问/admin就允许访问。

    退出系统
    访问’http://localhost:8080/spring_security_01_war/logout‘,之后会跳转到’http://localhost:8080/spring_security_01_war/index‘。

     

  • 相关阅读:
    串的模式匹配问题
    游戏手柄directinput编程
    Hibernate的generator属性的意义
    MySQL——基础入门
    IEbug——li标签之间的空隙
    struts2 jar包详解
    hibernate自动建库(MySQL)
    hibernate参数一览表
    js中的逻辑运算符
    hibernate的离线关联(多级)查询
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/12187868.html
Copyright © 2011-2022 走看看