SpringBoot

1、springboot概念

Spring Boot是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适)。

 

2、SpringBoot目录结构

1、com.*.*

Application.java 建议放到跟目录下面,主要用于做一些框架配置

2、com.*.*.domain

domain目录主要用于实体(Entity)与数据访问层(Repository)

3、com.*.*. service

service 层主要是业务类代码

4、com.*.*. controller

Controller层 负责页面访问控制

3、springBoot注解

1、@GeneratedValue注解

主键产生策略

strategy属性

-AUTO主键由程序控制, 是默认选项 ,不设置就是这个

-IDENTITY 主键由数据库生成, 采用数据库自增长, Oracle不支持这种方式

-SEQUENCE 通过数据库的序列产生主键, MYSQL 不支持

-Table 提供特定的数据库产生主键, 该方式更有利于数据库的移植

2、@Transient:

Entity中不映射成列的字段得加@Transient注解

3、@ConditionalOnProperty:

注解能够控制某个configuration是否生效。具体操作是通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值,如果该值为空,则返回false;如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。如果返回值为false,则该configuration不生效;为true则生效。

4、@ConfigurationProperties(prefix=“xxx”)

读取配置文件中以xxx开头的配置

5、@EnableCaching

使用缓存

6、@EnableScheduling

开启定时功能

7、@Scheduled

参数可以接受两种定时的设置,一种是我们常用的cron="*/6 * * * * ?",一种是 fixedRate = 6000,两种都表示每隔六秒打印一下内容。

  • @Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行
  • @Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行
  • @Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次

 

4、log4j日志输出级别

log4j规定了默认的几个级别:trace<debug<info<warn<error<fatal

5、Spring Data JPA数据库配置

1、pom依赖

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
     <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

2、添加配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/sulei
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver  //driver可以不用配置
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
 
spring.redis.database=0  
spring.redis.host=localhost
spring.redis.port=6379  
spring.redis.password=  
spring.redis.pool.max-active=8  
spring.redis.pool.max-wait=-1  
spring.redis.pool.max-idle=8  
spring.redis.pool.min-idle=0  
spring.redis.timeout=0

其实这个hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构,有四个值:

  1. create: 每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
  2. create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
  3. update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
  4. validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

dialect主要是指定生成表名的存储引擎为InneoDB
show-sql是否打印出自动生产的SQL,方便调试的时候查看

的属性设置为 create or create-drop的时候,spring boot 启动时默认会扫描classpath下面(项目中一般是resources目录)是否有import.sql,如果有机会执行import.sql脚本。

spring:
    datasource:
      schema: database/data.sql
      sql-script-encoding: utf-8
    jpa:
      hibernate:
        ddl-auto: none

:设置脚本的路径

:设置脚本的编码

3、dao层

dao只要继承JpaRepository类就可以,几乎可以不用写方法,还有一个特别的功能非常赞,就是可以根据方法名来自动的生产SQL,比如findByUserName 会自动生产一个以 userName 为参数的查询方法,比如 findAlll 自动会查询表里面的所有数据,比如自动分页等等。

public interface UserRepository extends  JpaRepository<User, Long> {
    User findByUserName(String userName);
 User findByUserNameOrEmail(String username, String email);
}

4、测试

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserRepositoryTests {
 @Autowired
 private UserRepository userRepository;
 @Test
 public void test() throws Exception {
 Date date = new Date();
 DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);        
 String fdate = dateFormat.format(date);
 userRepository.save(new User("aa","aa123456", "aa@126.com", "aa1",fdate));
 userRepository.save(new User("bb","bb123456", "bb@126.com", "bb1",fdate));
 userRepository.save(new User("cc","cc123456", "cc@126.com", "cc1",fdate));
 System.out.println(userRepository.findAll().size());
 System.out.println(userRepository.findByUnameOrEmail("bb", "bb@126.com").getNickName());
 userRepository.delete(userRepository.findByUname("aa"));
 }
}

Assert类中的方法调用的时候报错,不是程序的问题,而是断言与预期结果不符

5、开启缓存配置类

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
 @Bean
 public KeyGenerator keyGenerator() {
 return new KeyGenerator() {
 @Override
 public Object generate(Object target, Method method, Object... params) {
 StringBuilder sb = new StringBuilder();
 sb.append(target.getClass().getName());
 sb.append(method.getName());
 for (Object obj : params) {
 sb.append(obj.toString());
 }
 return sb.toString();
 }
 };
 }
 @SuppressWarnings("rawtypes")
 @Bean
 public CacheManager cacheManager(RedisTemplate redisTemplate) {
 RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
设置缓存过期时间
秒
 return rcm;
 }
 @SuppressWarnings({ "rawtypes", "unchecked" })
 @Bean
 public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
 StringRedisTemplate template = new StringRedisTemplate(factory);
 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 ObjectMapper om = new ObjectMapper();
 om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 jackson2JsonRedisSerializer.setObjectMapper(om);
 template.setValueSerializer(jackson2JsonRedisSerializer);
 template.afterPropertiesSet();
 return template;
 }
}

 

6、开启自动缓存

@RequestMapping("/getUser")
 @Cacheable(value="user")
 public User getUser() {
     User user=urepo.findByUname("bb");
     return user;
 }

其中value的值就是缓存到redis中的key

7、redis中session共享

1、引入依赖

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

2、Session配置:

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Boot的server.session.timeout属性不再生效

3、测试

@RequestMapping("/uid")
    String uid(HttpSession session) {
        UUID uid = (UUID) session.getAttribute("uid");
        if (uid == null) {
            uid = UUID.randomUUID();
        }
        session.setAttribute("uid", uid);
        return session.getId();
    }

4、如何在两台或者多台中共享session

其实就是按照上面的步骤在另一个项目中再次配置一次,启动后自动就进行了session共享。

8、多数据源配置

1、properties文件配置

spring.datasource.primary.url=jdbc:mysql://localhost:3306/temp
spring.datasource.primary.username=root
spring.datasource.primary.password=123
 
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123
 
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true

2、数据源配置

@Configuration
public class DataSourceConfig {
 @Bean(name = "primaryDataSource")
 @Qualifier("primaryDataSource")
 @Primary
 @ConfigurationProperties(prefix = "spring.datasource.primary")
 public DataSource primaryDataSource() {
 return DataSourceBuilder.create().build();
 }
 @Bean(name = "secondaryDataSource")
 @Qualifier("secondaryDataSource")
 @ConfigurationProperties(prefix = "spring.datasource.secondary")
 public DataSource secondaryDataSource() {
 return DataSourceBuilder.create().build();
 }
}

3、添加数据源的spring data jpa支持

主数据源:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactoryPrimary",       transactionManagerRef="transactionManagerPrimary",

设置Repository所在位置

public class PrimaryConfig {
    @Autowired 
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;
    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .properties(getVendorProperties(primaryDataSource))
设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }
    @Autowired
    private JpaProperties jpaProperties;
    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }
    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

其它数据源:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactorySecondary",      transactionManagerRef="transactionManagerSecondary",

设置Repository所在位置

public class SecondaryConfig {
    @Autowired @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }
    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondaryDataSource)
                .properties(getVendorProperties(secondaryDataSource))

设置实体类所在位置

.persistenceUnit("secondaryPersistenceUnit")
                .build();
    }
    @Autowired
    private JpaProperties jpaProperties;
    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }
    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }
}

9、异构数据库多源支持

  • 项目中,即需要对mysql的支持,也需要对mongodb的查询等。

实体类声明@Entity 关系型数据库支持类型、声明@Document 为mongodb支持类型,不同的数据源使用不同的实体就可以了

  • 如果User用户既使用mysql也使用mongodb呢,也可以做混合使用
  • 也可以通过对不同的包路径进行声明,比如A包路径下使用mysql,B包路径下使用mongoDB
@EnableJpaRepositories(basePackages = 
"com.neo.repositories.jpa")
@EnableMongoRepositories(basePackages = 
"com.neo.repositories.mongo")
  public interface Configuration { }

 

 

 

6、SpringBoot热启动实时生效

热启动在正常开发项目中改动项目后重启总是报错;但springBoot对调试支持很好,修改之后可以实时生效,需要添加配置:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
   </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
   </plugins>
</build>

7、springboot整合mybatis(注解)

1、pom配置

<dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.mybatis.spring.boot</groupId>
 <artifactId>mybatis-spring-boot-starter</artifactId>
 <version>1.1.1</version>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <optional>true</optional>
 </dependency>
 </dependencies>

2、配置文件

mybatis.type-aliases-package=com.sl.entity

3、mapper类扫描

  • 在启动类上加@MapperScan("mapper类包")
  • 在mapper类上加@Mapper注解

4、mapper类

public  interface  UserMapper {
    @Select("SELECT * FROM users")
    @Results({
        @Result(property = "userSex",  column = "user_sex", javaType = UserSexEnum.class),
        @Result(property = "nickName", column = "nick_name")
    })
    List<UserEntity> getAll();
 
    @Select("SELECT * FROM users WHERE id = #{id}")
    @Results({
        @Result(property = "userSex",  column = "user_sex", javaType = UserSexEnum.class),
        @Result(property = "nickName", column = "nick_name")
    })
    UserEntity getOne(Long id);
 
    @Insert("INSERT INTO users(userName,passWord,user_sex)           VALUES(#{userName}, #{passWord}, #{userSex})")
    void insert(UserEntity user);
 
    @Update("UPDATE users SET userName=#{userName},
    nick_name=#{nickName} WHERE id =#{id}")
    void update(UserEntity user);
 
    @Delete("DELETE FROM users WHERE id =#{id}")
    void delete(Long id);
}

user_sex使用了枚举

@Select 是查询类的注解,所有的查询均使用这个

@Result 修饰返回的结果集,关联实体类属性和数据库字段一一对应,如果实体类属性和数据库属性名保持一致,就不需要这个属性来修饰。

@Insert 插入数据库使用,直接传入实体类会自动解析属性到对应的值

@Update 负责修改,也可以直接传入对象

@Delete 负责删除

8、springboot整合mybatis(极简xml)

1、pom配置

<dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.mybatis.spring.boot</groupId>
 <artifactId>mybatis-spring-boot-starter</artifactId>
 <version>1.1.1</version>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <optional>true</optional>
 </dependency>
 </dependencies>

2、配置文件

mybatis.type-aliases-package=com.sl.entity
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis-config.xml 配置
<configuration>
    <typeAliases>
        <typeAlias alias="Integer" type="java.lang.Integer" />
        <typeAlias alias="Long" type="java.lang.Long" />
        <typeAlias alias="HashMap" type="java.util.HashMap" />
        <typeAlias  alias="LinkedHashMap"    type="java.util.LinkedHashMap" />
        <typeAlias alias="ArrayList" type="java.util.ArrayList" />
        <typeAlias alias="LinkedList" type="java.util.LinkedList" />
    </typeAliases>
</configuration>

这里也可以添加一些mybatis基础的配置

3、xxxMapper.xml

<mapper namespace="com.neo.mapper.UserMapper" >
    <resultMap id="BaseResultMap" type="com.neo.entity.UserEntity" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="userName" property="userName" jdbcType="VARCHAR" />
        <result column="passWord" property="passWord" jdbcType="VARCHAR" />
        <result column="user_sex" property="userSex" javaType="com.neo.enums.UserSexEnum"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR" />
    </resultMap>
 
    <sql id="Base_Column_List" >
        id, userName, passWord, user_sex, nick_name
    </sql>
 
    <select id="getAll" resultMap="BaseResultMap"  >
       SELECT 
       <include refid="Base_Column_List" />
       FROM users
    </select>
 
    <select id="getOne" parameterType="java.lang.Long" resultMap="BaseResultMap" >
        SELECT 
       <include refid="Base_Column_List" />
       FROM users
       WHERE id = #{id}
    </select>
 
    <insert id="insert" parameterType="com.neo.entity.UserEntity" >
       INSERT INTO 
            users
            (userName,passWord,user_sex) 
        VALUES
            (#{userName}, #{passWord}, #{userSex})
    </insert>
 
    <update id="update" parameterType="com.neo.entity.UserEntity" >
       UPDATE 
            users 
       SET 
        <if test="userName != null">userName = #{userName},</if>
        <if test="passWord != null">passWord = #{passWord},</if>
        nick_name = #{nickName}
       WHERE 
            id = #{id}
    </update>
 
    <delete id="delete" parameterType="java.lang.Long" >
       DELETE FROM
             users 
       WHERE 
             id =#{id}
    </delete>
</mapper>

4、mapper类

public  interface  UserMapper {
    List<UserEntity> getAll();
    UserEntity getOne(Long id);
    void insert(UserEntity user);
    void update(UserEntity user);
    void delete(Long id);
}

9、springboot+mybatis+多数据源

1、配置文件

mybatis.config-locations=classpath:mybatis/mybatis-config.xml

2、数据源配置

@Configuration
@MapperScan(basePackages = "com.neo.mapper.test1", 
sqlSessionTemplateRef  = "test1SqlSessionTemplate")
public class DataSource1Config {
    @Bean(name = "test1DataSource")
    @ConfigurationProperties(prefix = 
"spring.datasource.test1")
    @Primary
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "test1SqlSessionFactory")
    @Primary
    public SqlSessionFactory 
testSqlSessionFactory(@Qualifier("test1DataSource") 
DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new 
SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new 
PathMatchingResourcePatternResolver().getResource
s("classpath:mybatis/mapper/test1/*.xml"));
        return bean.getObject();
    }
    @Bean(name = "test1TransactionManager")
    @Primary
    public DataSourceTransactionManager 
testTransactionManager(@Qualifier("test1DataSource") 
DataSource dataSource) {
        return new 
DataSourceTransactionManager(dataSource);
    }
    @Bean(name = "test1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate 
testSqlSessionTemplate(@Qualifier("test1SqlSessionFac
tory") SqlSessionFactory sqlSessionFactory) throws 
Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

10、springboot+shiro

1、Apache Shiro

1、概念

是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密

2、应用场景

  • 验证用户身份
  • 用户访问权限控制,比如:1、判断用户是否分配了一定的安全

角色。2、判断用户是否被授予完成某个操作的权限

  • 在非 web 或 EJB 容器的环境下可以任意使用Session API
  • 可以响应认证、访问控制,或者
  • 生命周期中发生的事件
  • 可将一个或以上用户安全数据源数据组合成一个复合的用户

 "view"(视图)

  • 支持单点登录(SSO)功能
  • 支持提供“Remember Me”服务,获取用户关联信息而无需登录