zoukankan      html  css  js  c++  java
  • Spring学习笔记1——IOC: 尽量使用注解以及java代码

    在实战中学习Spring,本系列的最终目的是完成一个实现用户注册登录功能的项目。

    预想的基本流程如下:

    1、用户网站注册,填写用户名、密码、email、手机号信息,后台存入数据库后返回ok。(学习IOC,mybatis,SpringMVC的基础知识,表单数据验证,文件上传等)

    2、服务器异步发送邮件给注册用户。(学习消息队列)

    3、用户登录。(学习缓存、Spring Security)

    4、其他。

    边学习边总结,不定时更新。项目环境为Intellij + Spring4。

    一、准备工作。

    1、mysql中建库建表。

    2、Intellij中创建maven webapp工程。

    (1) pom.xml中导入需要的依赖包。

    <?xml version="1.0" encoding="UTF-8"?>
    <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/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.everSeeker</groupId>
        <artifactId>register</artifactId>
        <packaging>war</packaging>
        <version>1.0</version>
        <name>register Maven Webapp</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <spring.version>4.3.1.RELEASE</spring.version>
        </properties>
    
        <dependencies>
            <!--spring core, context-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!--test-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <!--<scope>test</scope>-->
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!--springmvc-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.2.4.Final</version>
            </dependency>
            <!--servlet-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
            <!--mysql, mybatis-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>6.0.3</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.1</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.3.0</version>
            </dependency>
            <dependency>
                <groupId>c3p0</groupId>
                <artifactId>c3p0</artifactId>
                <version>0.9.1.2</version>
            </dependency>
        </dependencies>
    
        <build>
            <finalName>java_config_web</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    pom.xml

    (2) 工程目录结构如下所示:

    二、Mybatis

    1、配置mysql数据库的基本信息。

    # Database
    db.mysql.driverClass = com.mysql.jdbc.Driver
    db.mysql.jdbcUrl = jdbc:mysql://localhost:3306/register_notice?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
    db.mysql.user = root
    db.mysql.password = 333
    db.minPoolSize = 10
    db.maxPoolSize = 100
    db.initialPoolSize = 20
    db.maxIdleTime = 60
    db.acquireIncrement = 5
    db.maxStatements = 100
    db.idleConnectionTestPeriod = 60
    db.acquireRetryAttempts = 30
    db.breakAfterAcquireFailure = true
    db.testConnectionOnCheckout = false
    db.properties

    2、配置mybatis.xml以及spring-mybatis.xml。

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    
        <!--配置实体类的别名-->
        <typeAliases>
            <!--以下2种方法选其一即可。 第1种方法:使用typeAlias,为单个类设置别名。-->
            <!--<typeAlias type="com.everSeeker.entity.User" alias="User" />-->
            
            <!--第2种方法:使用package,为包下面的所有类设置别名,默认规则为com.everSeeker.entity.User设置为User,去除前面的包名。-->
            <package name="com.everSeeker.entity" />
        </typeAliases>
    
    </configuration>
    mybatis.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:tx="http://www.springframework.org/schema/tx"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context.xsd
                               http://www.springframework.org/schema/tx
                               http://www.springframework.org/schema/tx/spring-tx.xsd">
    
           <!-- 在该文件中引入db.properties文件,可以保证之后的配置比如${db.mysql.driverClass}肯定能找到对应的值 -->
           <!-- 否则,如果直接在RootConfig.java中同事载入db.properties以及spring-mybatis.xml的话,不能保证db.properties先被引入,从而导致程序报错 -->
           <context:property-placeholder location="classpath:db.properties"/>
    
           <!--数据源配置 c3p0
               常见的数据源实现类包有2个,一个是apache的DBCP(org.apache.commons.dbcp.BasicDataSource),另一个为C3P0。
           -->
           <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
                 destroy-method="close">
    
                  <property name="driverClass" value="${db.mysql.driverClass}" />
                  <property name="jdbcUrl" value="${db.mysql.jdbcUrl}" />
                  <property name="user" value="${db.mysql.user}" />
                  <property name="password" value="${db.mysql.password}" />
    
                  <!--连接池中保留的最小连接数。 -->
                  <property name="minPoolSize" value="${db.minPoolSize}" />
    
                  <!--连接池中保留的最大连接数。Default: 15 -->
                  <property name="maxPoolSize" value="${db.maxPoolSize}" />
    
                  <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
                  <property name="initialPoolSize" value="${db.initialPoolSize}" />
    
                  <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
                  <property name="maxIdleTime" value="${db.maxIdleTime}" />
    
                  <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
                  <property name="acquireIncrement" value="${db.acquireIncrement}" />
    
                  <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
                      如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
                  <property name="maxStatements" value="${db.maxStatements}" />
    
                  <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
                  <property name="idleConnectionTestPeriod" value="${db.idleConnectionTestPeriod}" />
    
                  <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
                  <property name="acquireRetryAttempts" value="${db.acquireRetryAttempts}" />
    
                  <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
                      获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
                  <property name="breakAfterAcquireFailure" value="${db.breakAfterAcquireFailure}" />
    
                  <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
                      等方法来提升连接测试的性能。Default: false -->
                  <property name="testConnectionOnCheckout" value="${db.testConnectionOnCheckout}" />
           </bean>
    
           <!-- myBatis配置.
                classpath和classpath*的区别,参考文档:http://blog.csdn.net/zl3450341/article/details/9306983.
                classpath只会返回第一个匹配的资源,建议确定路径的单个文档使用classpath;匹配多个文档时使用classpath*.
           -->
           <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
                 p:dataSource-ref="dataSource"
                 p:configLocation="classpath:mybatis.xml"
                 p:mapperLocations="classpath*:mapper/*Mapper.xml" />
    
           <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                  <!--basePackage指定要扫描的包,在此包之下的映射器都会被搜索到。可指定多个包,包与包之间用逗号或分号分隔
                      MapperScannerConfigurer将扫描basePackage所指定包下的所有接口类(包括子包),如果他们在SQL映射文件
                      中定义过,则将他们动态定义为一个Spring Bean. -->
                  <property name="basePackage" value="com.everSeeker.dao" />
                  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
           </bean>
    
           <!-- 事务管理器配置, 使用jdbc事务 -->
           <bean id="transactionManager"
                 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  <property name="dataSource" ref="dataSource" />
           </bean>
    
           <!-- 使用annotation定义事务,对标注了@Transactional注解的bean进行处理,以织入事务管理切面.
               默认情况下,自动使用名称为transactionManager的事务管理器。
               proxy-target-class为true,表示spring将通过创建子类来代理业务类,需要在类路径中添加CGLib.jar类库。-->
           <tx:annotation-driven transaction-manager="transactionManager"
                                 proxy-target-class="true" />
    </beans>
    spring-mybatis.xml

    3、创建User类以及UserDao接口。

    public class User {
        @Size(min = 32, max = 32, message = "uuid应该为32位字符串")
        private String id;
    
        @Size(min = 1, max = 32, message = "账号长度应该在1-32位之间")
        private String username;
    
        @NotEmpty(message = "密码不能为空")
        private String password;
    
        @NotEmpty(message = "email不能为空")
        @Email(message = "email格式不正确")
        private String email;
    
        @Size(min = 11, max = 11, message = "手机号长度为11位")
        private String cellphone;
    
        private long regDate;
    
        public User() {
            this.id = UUID.randomUUID().toString().replaceAll("-", "");
            this.regDate = 0;
        }
    
        public User(String username, String password, String email, String cellphone) {
            this(username, password, email, cellphone, new Date().getTime());
        }
    
        public User(String username, String password, String email, String cellphone, long regDate) {
            this.id = UUID.randomUUID().toString().replaceAll("-", "");
            this.username = username;
            this.password = password;
            this.email = email;
            this.cellphone = cellphone;
            this.regDate = regDate;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String 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 String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public String getCellphone() {
            return cellphone;
        }
    
        public void setCellphone(String cellphone) {
            this.cellphone = cellphone;
        }
    
        public long getRegDate() {
            return regDate;
        }
    
        public void setRegDate(long regDate) {
            this.regDate = regDate;
        }
    
        @Override
        public String toString() {
            return "[User: id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", cellphone=" +
                    cellphone + ", regDate=" + regDate + "]";
        }
    }
    User.java

    User.java中的@NotNull, @NotEmpty, @Size以及@Email等注释暂时忽略,以后解释。

    @Repository
    public interface UserDao {
        void addUser(User user);
        User getUserByUsername(String username);
    }
    UserDao.java

    4、在src/main/resources/mapper目录下创建UserMapper.xml映射文件,实现UserDao接口中的方法。注:*Mapper.xml文件必须放在src/main/resources目录下,之前放在src/main/java/com/everSeeker/dao目录下,产生了莫名奇妙的错误。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.everSeeker.dao.UserDao">
        <resultMap id="ResultMapUser" type="com.everSeeker.entity.User">
        </resultMap>
    
        <insert id="addUser" parameterType="User">
            INSERT INTO user(id, username, password, email, cellphone, regDate) VALUES(#{id}, #{username}, #{password}, #{email}, #{cellphone}, #{regDate})
        </insert>
    
        <select id="getUserByUsername" parameterType="String" resultMap="ResultMapUser">
            SELECT * FROM user WHERE username=#{username}
        </select>
    
    </mapper>
    UserMapper.xml

    三、IOC

    1、创建IOC容器,通过注解方式,RootConfig.java。

    @Configuration
    @ComponentScan(basePackages = {"com.everSeeker"}, excludeFilters = {
            @ComponentScan.Filter(type = FilterType.CUSTOM, value = RootConfig.WebPackage.class)})
    @ImportResource({"classpath:spring-mybatis.xml"})
    public class RootConfig {
        public static class WebPackage extends RegexPatternTypeFilter {
            public WebPackage() {
                super(Pattern.compile("com\.everSeeker\.web"));
            }
        }
    }

    @Configuration: 表明这是一个配置类。

    @ComponentScan: 启用组建扫描,basePackages:需要扫描的基础package。excludeFilters: 符合filter条件的不扫描。

    @ImportResource: 引入xml文件。

    @PropertySource: 引入properties文件。

    2、由于创建的是webapp项目,并且采用了SpringMVC,那么DispatcherServlet是核心。以前的Spring版本中,一般会配置在web.xml中。而在Spring4中,可以在Java代码中来实现。WebAppInitializer.java。

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {  //继承了AbstractAnnotationConfigDispatcherServletInitializer的类会自动配置DispatcherServlet和Spring应用上下文
    
        @Override
        protected String[] getServletMappings() {       //将DispatcherServlet映射到"/"
            return new String[] { "/" };
        }
    
        /**
         * RootConfig类用来配置ContextLoaderListener创建的应用上下文中的bean,
         * 比如@Repository, @Service等组件
         */
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class<?>[] { RootConfig.class };
        }
    
        /**
         * DispatcherServlet加载应用上下文时,使用定义在WebConfig配置类中的bean,
         * 用来加载包含Web组件的bean,比如控制器,视图解析器以及处理器映射,  @Controller, @RequestMapping等
         */
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class<?>[] { WebConfig.class };
        }
    
        @Override
        protected void customizeRegistration(ServletRegistration.Dynamic registration) {
            //限制上传文件的大小不超过2MB,整个请求不超过4M,所有上传的文件都要写到磁盘中
            registration.setMultipartConfig(new MultipartConfigElement("/tmp/uploads", 2097152, 4194304, 0));
        }
    }

    3、创建WebConfig.java。

    @Configuration
    @EnableWebMvc
    @ComponentScan("com.everSeeker.web")
    public class WebConfig extends WebMvcConfigurerAdapter {
        //配置jsp视图解析器
        @Bean
        public ViewResolver viewResolver() {
            InternalResourceViewResolver resourceViewResolver = new InternalResourceViewResolver();
            resourceViewResolver.setPrefix("/WEB-INF/views/");
            resourceViewResolver.setSuffix(".jsp");
            resourceViewResolver.setExposeContextBeansAsAttributes(true);
            return resourceViewResolver;
        }
    
        //配置multipart解析器, 上传文件用
        @Bean
        public MultipartResolver multipartResolver() throws IOException {
            return new StandardServletMultipartResolver();
        }
    
        //配置静态资源的处理
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    }

    @Bean: 声明这个方法会创建所需类型的实例,并注册为Spring应用上下文中的bean。

    1、参考文献:Spring实战(第4版)。

    2、传送门:基于纯Java代码的Spring容器和Web容器零配置的思考和实现

  • 相关阅读:
    koa中静态文件资源中间件实现
    js数组扁平化
    js读写txt文件
    JDBC配置MSSQL
    Eclipse报错:Setting property 'source' to 'org.eclipse.jst.jee.server:xx' did not find a matching property
    JSON字符串的生成
    以POST方式推送JSON数据,并接收返回的服务器消息
    C# XML与Json之间相互转换实例详解
    eclipse配置Tomcat服务器server locations的方法
    uwsgi基础——SNMP
  • 原文地址:https://www.cnblogs.com/everSeeker/p/5667503.html
Copyright © 2011-2022 走看看