hello

未来学习计划

1、做计划,并同时写笔记

在四个月的时间里,我首先按照Java后端路线图(两个图结合着参考学习)安排好复习计划,每个知识点都安排一段时间。比如我可能花一天时间复习“Java反射”,两天时间复习“设计模式”,一周的时间用于复习”JVM虚拟机”。我一般会在月初做好整个月的计划,然后根据进度做一些微调。

2、整合知识点

3、做项目,也刷算法

跟着牛客网的项目课做了,这两个项目都使用SpringBoot快速开发,并且用到一些常用的后端技术比如redis,云存储,以及一些常见Web框架,除此之外还涉及到了solr,爬虫等技术。虽然项目不算很难,但是我在这段时间里很快地熟悉了完整项目开发的流程,并且每天做迭代,通过Git来跟进版本,每个版本都会写清所做的内容,这也让我对项目的架构非常熟悉。
在项目之余,我也找一些常用的后端组件来跑一跑demo,以便让我对这些技术有一个直观的了解,比如面试常问的dubbo,zookeeper,消息队列等组件。这些尝试也让我在理解它们的原理时更加得心应手了。)

4、坚持刷题,注重方法

首先我重新刷了一遍剑指offer,并且对每道题目进行总结,尽量保证每一道题都可以记在脑子里,众所周知剑指offer中的题是面试时非常喜欢考的,所以先搞定这部分题目是最为关键的。
搞定剑指offer之后,当然还要刷LeetCode了,LeetCode题目这么多,怎么选择呢,我没有按照tag刷,也没有按照顺序刷,而是参考当时一个大佬的LeetCode刷题指南来进行刷题的,他把每个类型的题目都做了归纳,每部分只放一些比较经典的题目。所以我前后大概刷了100多道LeetCode的题目,并且在第二遍刷题复习的时候,我也对这些题目做了一份总结。

除了上面两个经典题库,我还着重刷了大厂的历年真题,这部分我主要是通过牛客网的历年真题题库来完成刷题的。说实话,真题是非常重要的,因为公司出的题目不像平时的那些算法题,可能会出得非常奇葩,所以你如果不提前适应的话会比较吃亏。完成这部分题目之后,我对算法题的复习也基本告一段落了。

算法第四版:入门书籍,非常好。

11分钟实现springBoot整合springcahe组件

11分钟实现springBoot整合springcahe组件

宁可清贫自乐,不可浊富多忧


一、是什么

SpringCache本身是一个缓存体系的抽象实现,并没有具体的缓存能力,要使用SpringCache还需要配合具体的缓存实现来完成。

缓存作用是将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法;

二、分析

CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;

  • 原理:

    1、自动配置类 CacheAutoConfiguration

    2、缓存的配置类

    org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
    
    org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】
    
    org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
    

    3、哪个配置类默认生效:SimpleCacheConfiguration

    4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager

    5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;

  • 运行流程:

    @Cacheable:

    1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;

    (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。

    2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;

    key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;

    ​ SimpleKeyGenerator生成key的默认策略;

    ​ 如果没有参数;key=new SimpleKey();

    ​ 如果有一个参数:key=参数的值

    ​ 如果有多个参数:key=new SimpleKey(params);

    3、没有查到缓存就调用目标方法;

    4、将目标方法返回的结果,放进缓存中

    ​ @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,

    ​ 如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;

  • 核心:

    1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件

    2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator

三、注解使用

@Cacheable:触发缓存

  • 常用属性:

    • cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
    • key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值 1-方法的返回值

    ​ 编写SpEL; #i d;参数id的值 #a0 #p0 #root.args[0]

    ​ getEmp[2]

    • keyGenerator:key的生成器;可以自己指定key的生成器的组件id

    • key/keyGenerator:二选一使用;

    • cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器

    • condition:指定符合条件的情况下才缓存;

    ​ ,condition = “#id>0”

    ​ condition = “#a0>1”:第一个参数的值》1的时候才进行缓存

    • unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断

    ​ unless = “#result == null”

    ​ unless = “#a0==2”:如果第一个参数的值是2,结果不缓存;

    • sync:是否使用异步模式
    • 自定义 keyGenerator:
    @Configuration 
    public class MyCacheConfig {     
    @Bean("myKeyGenerator")    
    public KeyGenerator keyGenerator(){        
        return new KeyGenerator(){             
            public Object generate(Object target, Method method, Object... params) {                            return method.getName()+"["+ Arrays.asList(params).toString()+"]";            
            }        
        };    
    } 
    }
    

@CachePut:缓存更新

既调用方法,又更新缓存数据;同步更新缓存

修改了数据库的某个数据,同时更新缓存;

  • 运行时机:

    1、先调用目标方法

    2、将目标方法的结果缓存起来

@CacheEvict:缓存清除

​ 代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除

  • key:指定要清除的数据

  • allEntries = true:指定清除这个缓存中所有的数据

  • beforeInvocation = false:缓存的清除是否在方法之前执行

  • 默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除

    beforeInvocation = true:

四、SpEl

11分钟实现springBoot打war包和发布

11分钟实现springBoot打war包和发布

平安是幸,知足是福,清心是禄,寡欲是寿

用springBoot使开发变得很简便,其内置Tomcat更是实现了无法外置Tomcat启动项目,大大提高了便利性,然而有时候需要统一管理程序,或发布多个同端口项目时,不得不得打包成War包,方便防止在所需发布的服务器上。

一、修改打包形式

在pom.xml里设置

    <packaging>war</packaging>

二、移除嵌入式tomcat插件

在pom.xml里找到spring-boot-starter-web依赖节点,添加之间的内容,

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 移除嵌入式tomcat插件 -->
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

三、添加servlet-api的依赖

下面两种方式都可以,任选其一

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-servlet-api</artifactId>
        <version>8.0.36</version>
        <scope>provided</scope>
    </dependency>

四、修改启动类,并重写初始化方法

平常用main方法启动的方式,都有一个App的启动类,代码如下:

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

需要类似于web.xml的配置方式来启动spring上下文了,在Application类的同级添加一个SpringBootStartApplication类,其代码如下:

    /**
     * 修改启动类,继承 SpringBootServletInitializer 并重写 configure 方法
     */
    public class SpringBootStartApplication extends SpringBootServletInitializer {
     
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            // 注意这里要指向原先用main方法执行的Application启动类
            return builder.sources(Application.class);
        }
    }

五 application.propertis添加

当需要发布多个springboot项目到tomcat时需要添加如下,否则报错如下

Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [HikariDataSource (HikariPool-2)] with key ‘dataSource’; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=dataSource,type=HikariDataSource

    spring.jmx.enabled=false;

或者如下:

    spring.jmx.default-domain

六、打包部署

11分钟学会springboot热部署

11分钟学会springboot热部署

一个人的快乐,不是因为他拥有的多,而是因为他计较的少。

一、spring-boot-devtools

spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用。

devtools的原理

深层原理是使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,这样在有代码更改的时候,原来的restart ClassLoader 被丢弃,重新创建一个restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间。

1.添加以下的配置:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
</dependency>

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
     <!--fork:如果没有该项配置,整个devtools不会起作用-->
        <fork>true</fork>
    </configuration>
</plugin>

说明:

(1) devtools可以实现页面热部署(即页面修改后会立即生效,这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实现),
实现类文件热部署(类文件修改后不会立即生效),实现对属性文件的热部署。
即devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的

(2)配置了true后在修改java文件后也就支持了热启动,不过这种方式是属于项目重启(速度比较快的项目重启),会清空session中的值,也就是如果有用户登陆的话,项目重启后需要重新登陆。

默认情况下,/META-INF/maven,/META-INF/resources,/resources,/static,/templates,/public这些文件夹下的文件修改不会使应用重启,但是会重新加载(devtools内嵌了一个LiveReload server,当资源发生改变时,浏览器刷新)。

devtools的配置

在application.properties中配置spring.devtools.restart.enabled=false,此时restart类加载器还会初始化,但不会监视文件更新。

在SprintApplication.run之前调用System.setProperty(“spring.devtools.restart.enabled”, “false”);可以完全关闭重启支持,配置内容:

#热部署生效
spring.devtools.restart.enabled: true
#设置重启的目录
#spring.devtools.restart.additional-paths: src/main/java
#classpath目录下的WEB-INF文件夹内容修改不重启
spring.devtools.restart.exclude: WEB-INF/**

二选一

 #热部署
 devtools:
   restart:
     enabled: true
     additional-paths: src/main/java

2.设置IDEA的自动编译:

File-Settings-Compiler勾选 Build Project automatically

3..设置IDEA允许

快捷键 ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running

11分钟了解logback的配置和使用

11分钟了解logback的配置和使用

不论你在什么时候开始,重要的是开始之后就不要停止

一、logback简介

Logback 继承自 log4j。

Logback 的架构非常通用,适用不同的使用场景。Logback 被分成三个不同的模块:logback-core,logback-classic,logback-access。

logback-core 是其它两个模块的基础。logback-classic 模块可以看作是 log4j 的一个优化版本,它天然的支持 SLF4J,所以你可以随意的从其它日志框架(例如:log4j 或者 java.util.logging)切回到 logack。

logback-access 可以与 Servlet 容器进行整合,例如:Tomcat、Jetty。它提供了 http 访问日志的功能。

二、logback配置

<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="atguigu-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
            %d表示日期时间,
            %thread表示线程名,
            %-5level:级别从左显示5个字符宽度
            %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
            %msg:日志消息,
            %n是换行符
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 
            可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
            且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
            那些为了归档而创建的目录也会被删除。
            -->
            <MaxHistory>365</MaxHistory>
            <!-- 
            当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 日志输出格式: -->     
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 
        logger主要用于存放日志对象,也可以定义日志类型、级别
        name:表示匹配的logger类型前缀,也就是包的前半部分
        level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
        additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
        false:表示只用当前logger的appender-ref,true:
        表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->
    <!-- hibernate logger -->
    <logger name="com.atguigu" level="debug" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>
    
    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
    -->
    <root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 

11分钟了解Java中lombok使用

11分钟了解Java中lombok使用

让我们将事前的忧虑,换为事前的思考和计划吧


一、Lombok是什么?

Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或setter方法,同时可以自动化变量。意思就是说可以只通过一个注解就让编译器自动编译类是getter、setter等重复写的方法。

官方介绍
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.

二、如果使用?

1.添加依赖

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
        <scope>provided</scope>
    </dependency>

2.添加插件

在idea上安装lombok插件,并在File-Settings-build-AnnocationProcessors启用

开启该项是为了让Lombok注解在编译阶段起到作用。

3.常用注解

官方文档地址

val
注解在字段,不可变局部变量

var
注解在字段,可变局部变量

@NonNull
注解在参数上,判断不为空,抛出NullPointerException

@Cleanup
执行调用close方法

@Getter/@Setter
注解在类或字段,注解在类时为所有字段生成Getter/setter方法,注解在字段上时只为该字段生成Getter/setter方法

@ToString
注解在类,添加toString方法

@EqualsAndHashCode
注解在类,生成hashCode和equals方法

@NoArgsConstructor
注解在类,生成无参的构造方法

@RequiredArgsConstructor 
注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。

@AllArgsConstructor
注解在类,生成包含类中所有字段的构造方法

@Data
注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法

@Value
注解在类,相当于:final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter

@Builder
注解在类,注解后可赋值新对象和修改原对象的属性值

@SneakyThrows
注解在方法上,相当于添加了try-catch捕捉异常

@Synchronized
注解在方法上,锁定一个private的常量。如果当前类中没有这个常量,就会自动生成一个。


@Getter(lazy=true)
Getter高级版,会提高代码效率,同时由Lombok帮助你管理线程安全问题

11分钟了解Spring及mybatis等xml常见配置

11分钟了解Spring及mybatis等xml常见配置

世界会向那些有目标和远见的人让路。

总所周知,在使用Spring、SpringMVC和mybatis开发时,往往要配置的文件信息太多了,自己敲的话太麻烦了,以下整理了关于了常见的配置信息,可直接复制粘贴修改使用就好啦。

1.web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
id="WebApp_ID" version="3.1">

<!-- 欢迎页 -->
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- 配置Spring -->
  <context-param> 
    <param-name> contextConfigLocation </param-name> 
    <param-value>classpath:applicationContext.xml</param-value> 
</context-param> 

<!-- 配置监听器 -->
<listener> 
    <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> 
</listener>

  <!-- 前端配置器 spring mvc-->
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
  <!-- 中文处理过滤 -->
  <filter>
    <filter-name>Encoding</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>Encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

2. applicationContext.xml:

<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:aop="http://www.springframework.org/schema/aop" 
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-4.3.xsd 
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd 
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

<!-- 加载db.properties -->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 加载log4j.properties -->
<context:property-placeholder location="classpath:log4j.properties" />

<!-- 配置数据源 -->
<bean id="datasource" class="org.apache.commons.dbcp2.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <!-- 最大连接数 -->
    <property name="maxTotal" value="${jdbc.maxTotal}"></property> 
     <!-- 最大空闲连接数 -->
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>
     <!-- 初始化连接数 -->
     <property name="initialSize" value="${jdbc.initialSize}"></property> 
</bean>

<!-- 配置事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="datasource"/>
</bean>

<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

<!-- 配置 MyBatis的工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 数据源 -->
    <property name="dataSource" ref="datasource" />
    <!-- 配置MyBatis的核心配置文件所在位置 -->
    <property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>

<!-- 配置Mapper 自动扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.dao"></property>
</bean>

<!-- 开启注解扫描com.service -->    
<context:component-scan base-package="com.service"/>

</beans>

3. mybatis-config.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>
        <package name="com.po"/>
    </typeAliases>
    <mappers>
        <mapper resource="com/dao/Userdao.xml"/>
    </mappers>
</configuration>

4.mybatis-mapper.xml

<?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.mapper.StudentMapper">
    <select id="findbyid" parameterType="Integer" resultMap="StudentResult">
        select *from student where id=#{id}
    </select>

</mapper>

5.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/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/mvc
                          http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<context:component-scan base-package="com.controller"></context:component-scan>
<!--<bean name="/index" class="com.controller.Controller1 "/>-->

<!-- 定义视图 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>

<!-- 配置注解驱动 
    自动注册org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
    和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter -->
<mvc:annotation-driven />

<!-- 配置静态资源的访问映射 使其不被前端控制器拦截 -->
<mvc:resources location="/js/" mapping="/js/**" />
<!-- 使用使用默认的服务器请求处理器自动判断筛选 -->
<!-- <mvc:default-servlet-handler/> -->

<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 全局拦截器 -->
    <!--<bean class="" />  -->
    <mvc:interceptor>
           <mvc:mapping path="/**"/> <!-- 配置拦截器作用的路径 -->
        <mvc:exclude-mapping path=""/> <!-- 配置拦截器不作用的路径 -->
           <bean class="com.interceptor.LoginInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

<!-- 配置文件上传解析器 multipartResolver -->
<!-- 因为CommonsMultipartResolver内部是引用MultipartResolver字符串来完成文件解析 所以指定的ID必须为multipartResolver  -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 配置缓存中最大阈值 低于此值,只保留在内存里,超过此阈值,生成硬盘上的临时文件 -->
    <property name="maxInMemorySize" value="" /> 
    <!-- 推迟文件解析 -->
    <property name="resolveLazily" value=""/>
    <!-- 允许文件上传的最大尺寸 -->
    <property name="maxUploadSize" value="10485760" />
    <!-- 默认编码格式 -->
    <property name="defaultEncoding" value="UTF-8" />
</bean>
    
<!-- 显示装配的自定义的转换器 -->
<!-- <mvc:annotation-driven conversion-service="conversionservice1"></mvc:annotation-driven> -->

<!-- 自定义类型转换器配置 converters-->
<!-- <bean id="conversionservice1" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.converter.DateConverter"></bean>
        </set>
    </property>
</bean> -->

<!-- 自定义类型转换器配置formatters-->
<!-- <bean id="conversionservice2" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="formatters">
        <set>
            <bean class="com.converter.DateFormatter"></bean>
        </set>
    </property>
</bean> -->

</beans>

6.db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test1
jdbc.username=root
jdbc.password=123456
jdbc.maxTotal=30
jdbc.maxIdle=10
jdbc.initialSize=5

7.log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

11分钟了解Spring是什么

11分钟了解Spring是什么

有志者自有千计万计,无志者只感千难万难。

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

1.Spring框架包的下载

http://repo.spring.io/simple/libs-release-local/org/springframework/spring/

2.spring框架体系

image

3.spring 核心容器

  • BeanFactory接口:

    Resource resource = new FileSystemResource(“beans.xml”);
    BeanFactora factory = new XmlBeanFactory(resource);

  • ApplicationContext接口:

    从类路径下加载配置文件: ClassPathXmlApplicationContext

    从硬盘的绝对路径下加载配置文件: FileSystemXmlApplication

4.spring配置详解

4.1、元素属性

  • bean元素:使用该元素描述需要spring容器管理对象

  • name属性:给被管理的对象起个名字,获得对象时getBean(“name值”)

  • class属性:被管理对象的完整类名

  • id属性:与name属性一模一样,名称不可重复,不能使用特殊字符

name和id之间的一些注意点:

1 配置两个相同的 id 或者 name 都不能通过。

2 如果既配置了 id ,也配置了 name ,则两个都生效。如果id和name都没有指定,则用类全名作为name,如<bean class="com.stamen.BeanLifeCycleImpl">,则你可以通过getBean("com.stamen.BeanLifeCycleImpl")返回该实例

3 如果配置基本类的时候,注解和配置文件都使用的时候,注解和配置文件中 name 相同的时候, 则两个冲突,配置文件生效。如果配置基本类的时候,注解和配置文件都使用的时候,注解和配置文件中 name 不相同的时候, 则两个不冲突,都能够生效。

4.2、bean元素进阶

  1. scope属性

    (1) singleton (默认值 )

    单例对象:被标识为单例的对象在spring容器中只会存在一个实例

    (2) prototype

    多例原型:被标识为多例的对象,每次在获得才会被创建,每次创建都是新的对象

    (3)request

    Web环境下,对象与request生命周期一致

    (4)session

    Web环境下,对象与session生命周期一致

总结:绝大多数情况下,使用单例singleton(默认值),但是在与struts整合时候,务必要用prototype多例,因为struts2在每次请求都会创建一个新的Action,若为单例,在多请求情况下,每个请求找找spring拿的都是同一个action。

  1. 生命周期属性(了解)———初始化和销毁 (1)配置一个方法作为生命周期初始化方法,spring会在对象创建之后立刻调用 init-method (2)配置一个方法作为生命周期的销毁方法,spring容器在关闭并销毁所有容器中的对象之前调用destory-method
     <bean init-method=“init”  destory-method=“destory”></bean>
     //对应注解为@PostConstruct
     <bean name=“hello” class=“完整类名”></bean>
     //对应注解为@PreDestory
    
  1. 模块化配置,即分模块配置(导入其他spring配置文件)

     <beans>
         <import resource = “spring配置文件的全路径名” />
     </beans>
    

4.3、spring三种对象的创建方式

(1)空参数构造(重要)

(2)静态工厂创建(调用静态方法创建)调用UserFactory类的静态createUser方法创建名为user的对象,放入容器
    <bean name="user" class="cn.itcats.UserFactory" factory-method="createUser"></bean>

(3)实例工厂创建(调用非静态方法创建)——需要配置两个bean,因为无法通过类名调用非静态方法
    <bean name="user2" factory-bean="userFactory" factory-method="createUser"></bean>
    <bean name=“userFactory” class=“cn.itcats.UserFactory”></bean>

11分钟了解Spring JDBC和事务管理

11分钟了解Spring JDBC和事务管理

不断的努力,不断的去接近梦想,越挫越勇,吃尽酸甜苦辣,能够抵御寒冬,也能够拥抱春天,这样的才叫生活。

1. Spring JDBC 配置

1.1 对应的包类:

  • org.springframework.jdbc.core.JdbcTemplate 提供访问数据库基本属性和操作
  • org.springframework.jdbc.datasource.DriverManagerDataSource 获取数据库连接
  • org.springframework.jdbc.support.SQLExceptionTranslator 处理SQL Exception 完成转译
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/classes"/>
        <property name="username" value="root"/>
        <property name="password" value="123456" />
    </bean>    
    <bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="datasource"></property>
    </bean>

1.2 JdbcTemplate 常用方法

1.2.1数据库创建创建删除修改等:
    execute()  
1.2.2数据的增删改 :
  • int update(String sql) 执行Sql语句 返回受影响的行数;
  • int update(PrepareedStatementCreator psc) 执行 PrepareedStatementCreator 返回语句 返回行数;
  • int update(String sql,PrepareedStatementCreator psc) 执行 PrepareedStatementCreator 设置的Sql 语句 返回行数;
  • int update(String sql,Object..args) 使用Object…设置Sql语句中的参数,参数不能为NULL 返回行数;
    public int upadte(Userdao userdao) {
            String sql="update user set username=?,password=? where id=?";
            Object[] object=new Object[]{
                    userdao.getUsername(),
                    userdao.getPassword(),
                    userdao.getId()
            };
            int i=this.jdbcTemplate.update(sql, object);
            return i;
        }
1.2.3 数据表的查询
  • List query(String sql,RowMapper rowmapper) 执行Sql语句 通过RowMapper返回一个List集合;
  • List query(String sql,PrepareedStatementCreator psc,RowMapper rowmapper) 执行sql语句创建PrepareedStatement对象,通过RowMapper返回一个List对象;
  • List query(String sql,Object[] args,RowMapper rowmapper) 使用Object[] 的值设置Sql语句参数,采用RowMapper回调方法返回LIST 数据;
  • queryForObject(String sql,RowMapper rowmapper,Object..args) 将args 参数绑定Sql语句中,通过RowMapper返回一个Object类型的单行记录;
  • queryForList(String sql,Object[] args,class elementType) 返回多行数据的结果,但必须是返回列表,elementType 参数返回的是List 元素类型;

2.Spring 事务管理

2.1 Spring 所需要包类:

spring-tx-4.3.6.RELEASE.jar

2.2 事务管理器:

  • DataSourceTransactionManager :

    位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理;

  • JdoTransactionManager :

    位于org.springframework.orm.jdo包中,提供对单个javax.jdo.PersistenceManagerFactory事务管理,用于集成JDO框架时的事务管理;

  • JpaTransactionManager :

    位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理;

  • HibernateTransactionManager :

    位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;

  • JtaTransactionManager :

    位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器;

  • OC4JjtaTransactionManager :

    位于org.springframework.transaction.jta包中,Spring提供的对OC4J10.1.3+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;

  • WebSphereUowTransactionManager :

    位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;

  • WebLogicJtaTransactionManager :

    位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持。

2.3 事务定义:

声明式事务通过 -传播行为,隔离级别,只读提示,事务超时及回滚规则-来进行定义。

2.3.1事务传播行为:

image

2.4 基于XML 声明事务

    <!--配置事务管理器 依赖数据源  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"></property>
    </bean>
    <!-- 配置事务通知 -->
    <tx:advice id="txadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" 
    isolation="DEFAULT" read-only="false" timeout="-1" />
        </tx:attributes>
    </tx:advice>
    <!-- 配置AOP -->
    <aop:config>
        <aop:pointcut id="pointcut1" expression="execution(* com.dao.*.*(..))" />
        <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
    </aop:config>

2.5 基于Annotation 声明事务

    <!--配置事务管理器 依赖数据源  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"></property>
    </bean>
    <!-- 配置事务通知 -->
    <tx:annotation-driven transaction-manager="transactionManager" />

在使用的bean类或方法前 添加 @Transactional