spring框架实现
本次介绍只基于后端,非web,转换成web就添加web层基于servlet进行前后端交互就可以了
这种虽然说是spring框架,但是都是基于maven进行开发,所以创建项目是创建一个maven项目,然后添加spring依赖进行基于spring框架进行开发
1.基础maven类型
基础maven类型,与maven框架开发差不多,只不过加入了spring依赖,其中内部逻辑是不变的,但是不同的是在spring中,xml配置文件连接service和dao层方式是不一样的,除此之外一模一样.
基础版架构:
1.开发准备–pom.xml添加spring依赖
maven项目开发第一步,添加依赖和插件,因为我们不是web项目,不需要添加tomcat插件,不过web和非web项目开发是一致的,没什么差别
pom.xml中需要添加的依赖
<dependencies>
<!--mybatis包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--连接mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--spring依赖包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--线程池包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!--mybatis-spring整合包(主要配置)-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
2.创建properties文件
依赖环境添加好之后,我们就可以进行项目开发了,因为要进行数据库的操作,所以我们先创建一个数据库连接配置----里面的数据库名和用户密码设置自己的
创建一个jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root
还是三层架构开发
因为没有前后端的交互,所以web层就没了,只有后端的dao层和service层
3.domain层创建实体类javabean
看看数据库里面有什么,哇,原来是这
三列,分别为id(int),name(string),money(double)–之后的案例也是用这个数据库
所以在domain层中创建一个实体类Account
因为只是简单介绍,里面直接添加tostring输出数据
public class Account implements Serializable {
private Integer id;
private String name;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
4.dao层操作
创建了实体类,我们就可以创建dao层进行数据库操作了,在这里你想对数据库做什么就做什么
创建一个接口AccountDao,在里面我们进行对数据库的增删改查操作
public interface AccountDao {
void save(Account account);
void delete(Integer id);
void update(Account account);
List<Account> findAll();
Account findById(Integer id);
}
这样一个简单的dao就搞定了,既然dao添加了相应方法,我们就得在对应的资源文件中进行数据库语句的添加
5.resources中对应dao配置文件添加
dao在哪我在哪,dao有啥我有啥
在resources对应dao层也搞一个对应AccountDao接口的AccountDao.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.dou.dao.AccountDao">
<!--配置根据id查询-->
<select id="findById" resultType="account" parameterType="int">
select * from spring where id = #{id}
</select>
<!--配置查询所有-->
<select id="findAll" resultType="account">
select * from spring
</select>
<!--配置保存-->
<insert id="save" parameterType="account">
insert into spring(name,money)values(#{name},#{money})
</insert>
<!--配置删除-->
<delete id="delete" parameterType="int">
delete from spring where id = #{id}
</delete>
<!--配置根据名称查询-->
<select id="findByName" resultType="account" parameterType="string">
select * from spring where name = #{name}
</select>
<!--配置更新-->
<update id="update" parameterType="account">
update spring set name=#{name},money=#{money} where id=#{id}
</update>
</mapper>
6.业务层service开发
dao层搞好了,对应数据库连接也搞好了,接着就是业务层实现了,业务层怎么搞呢,
先做业务接口创建对应方法, 然后进行Impl业务逻辑实现
创建AccountService接口:
public interface AccountService {
void save(Account account);
void delete(Integer id);
void update(Account account);
List<Account> findAll();
Account findById(Integer id);
}
然后在业务层中创建包Impl,这个主要是区分一下方法和实现,在Impl下创建AccountServiceImpl实现类,继承AccountService接口
因为没交互,所以…极其简单
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void save(Account account) {
accountDao.save(account);
}
public void update(Account account){
accountDao.update(account);
}
public void delete(Integer id) {
accountDao.delete(id);
}
public Account findById(Integer id) {
return accountDao.findById(id);
}
public List<Account> findAll() {
return accountDao.findAll();
}
}
7.spring环境配置文件
数据库也连接了,实现类也实现了,然后把spring的环境配置好就可以进行应用了
在resources下面创建一个applicationContext.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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!--加载配置文件 *号是是个properties文件我就加载-->
<context:property-placeholder location="classpath:*.properties"/>
<!--数据库信息-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置service作为spring的bean,注入dao-->
<bean id="accountService" class="com.dou.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!--spring整合mybatis后控制创建连接的对象-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据库连接-->
<property name="dataSource" ref="dataSource"/>
<!--domain起别名-->
<property name="typeAliasesPackage" value="com.dou.domain"/>
</bean>
<!--//扫描org.mybatis.spring.sample.mapper下的所有接口(各种增删改查等),然后创建各自接口的动态代理类。-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dou.dao"/>
</bean>
</beans>
里面是什么东西呢,就是以前maven项目中mapper映射文件里面的内容,可以对比一下,一毛一样(对比代码)
**maven----**
<!--定义property的配置-->
<properties resource="jdbc.properties"></properties>
**spring----**
<!--加载配置文件-->
<context:property-placeholder location="classpath:*.properties"/>
**maven----**
<!--配置别名:别名配置是给实体类用的,不能用在dao上-->
<typeAliases>
<!--指定实体类所在的包,此时包下所有类都会注册别名,别名就是类名称-->
<package name="com.itheima.domain"></package>
</typeAliases>
**spring----**
<!--domain起别名-->
<property name="typeAliasesPackage" value="com.dou.domain"/>
**maven----**
<!--配置默认环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源信息-->
<dataSource type="POOLED" >
<!--配置连接数据库的四个基本信息-->
<property name="driver" 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>
</dataSource>
</environment>
</environments>
**spring----**
<!--数据库信息-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
**maven----**
<!--配置映射配置文件的位置-->
<mappers>
<!--指定实体映射配置文件所在的包,指定的是dao接口所在的包-->
<package name="com.itheima.dao"></package>
</mappers>
**spring----**
<!--//扫描org.mybatis.spring.sample.mapper下的所有接口(各种增删改查等),然后创建各自接口的动态代理类。-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dou.dao"/>
</bean>
8.运行一下子
配置结束,随便写个main实现一下就行
在java下创建一个App类去连接配置文件,调用其中的方法,看看是不是实现了
public class App {
public static void main(String[] args) {
//连接配置文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对应Dao接口bean,类型需要强转为服务层接口类
AccountService accountService= (AccountService) ctx.getBean("accountService");
//方法实现:
//查看
List<Account> all1 = accountService.findAll();
System.out.println(all1);
//保存
Account account = new Account(2,"张飞",33.3);
accountService.save(account);
//单个查看
Account ac1 = accountService.findById(2);
System.out.println(ac1);
//修改4,名字变成寒蝉
account.setName("寒蝉");
accountService.update(account);
//单个查看
Account ac2 = accountService.findById(2);
System.out.println(ac2);
//删除
accountService.delete(2);
//查看
List<Account> all2 = accountService.findAll();
System.out.println(all2);
}
}
2.纯注解开发型
注释使我们人能看懂的
注解就是计算机能看懂的语言,用了注解计算机会自动判断识别并进行操作,简化代码
1.pom.xml添加依赖
这个是跟基础类型的依赖相同的,没有特殊添加,因为第一个把maven整合spring依赖加进去了,基础版是不需要的,主要是用于添加一些注解的
2.配置文件转换为配置类
配置文件全部以注解形式体现,注解就是为了消除配置文件,把resources中的文件全部消除
比如AccountDao.xml中的文件,是连接dao和数据库的窗口:
<!--配置根据id查询-->
<select id="findById" resultType="account" parameterType="int">
select * from spring where id = #{id}
</select>
<!--配置查询所有-->
<select id="findAll" resultType="account">
select * from spring
</select>
<!--配置保存-->
<insert id="save" parameterType="account">
insert into spring(id,name,money)values(#{id},#{name},#{money})
</insert>
<!--配置删除-->
<delete id="delete" parameterType="int">
delete from spring where id = #{id}
</delete>
<!--配置根据名称查询-->
<select id="findByName" resultType="account" parameterType="string">
select * from spring where name = #{name}
</select>
<!--配置更新-->
<update id="update" parameterType="account">
update spring set name=#{name},money=#{money} where id=#{id}
</update>
这些语句不用再创建类,直接用以前maven项目经验,在AccountDao接口中直接注解在接口方法上(没有什么好坏的说法,都一个熊样)
public interface AccountDao {
@Insert("insert into spring (id,name,monry) values(#{id},#{name},#{monry})")
void save(Account account);
@Delete("delete from spring where id = #{id}")
void delete(Integer id);
@Update("update spring set name=#{name},money=#{money} where id=#{id}")
void update(Account account);
@Select("select * from spring")
List<Account> findAll();
@Select("select * from spring where id=#{id}")
Account findById(Integer id);
}
然后是jdbc.properties文件了,里面是连接的数据库信息:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root
这个文件比较特殊,所以就另外创建配置类添加信息
比如创建一个包config专门存放java配置类
然后在config包下创建一个JDBCConfig类,存放连接数据库的信息
public class JDBCConfig {
//value设置对应属性的值(或对方法)进行传参
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring_db")
private String url;
@Value("root")
private String username;
@Value("root")
private String password;
//设置该方法的返回值作为spring管理的bean,作用:连接数据库
@Bean("dataSource")
public DataSource DataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
然后就是重点了,applicationContext.xml文件就不需要了,直接转换:
<!--加载配置文件--> --不需要这个文件了,转换成配置类了,会直接在主配置类中加载
<context:property-placeholder location="classpath:*.properties"/>
<!--数据库信息--> --这个就转换到JDBCConfig类中
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> --
<!--配置service作为spring的bean,注入dao-->
<!--现在@Service("accountService")和@Autowired private AccountDao accountDao就可以实现引入类型注入,set方法也就不需要了;-->
<bean id="accountService" class="com.dou.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!--spring整合mybatis后控制创建连接的对象--> --数据库连接也已经放进JDBCConfig配置类中去了
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据库连接-->
<property name="dataSource" ref="dataSource"/>
<!--domain起别名--> --放进了MyBatisConfig
<property name="typeAliasesPackage" value="com.dou.domain"/>
</bean>
<!--//扫描org.mybatis.spring.sample.mapper下的所有接口(各种增删改查等),然后创建各自接口的动态代理类。-->
--也放进了MyBatisConfig
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dou.dao"/>
</bean>
</beans>
转换成注解的话先在config包下创建一个核心配置类,例如SpringConfig,使用注解时要先在核心配置类添加@Configuration,设置项目开发为纯注解格式,设置当前类为spring核心配置加载类,其他次要第三方类直接集合形式导入,第三方类就例如JDBCCofig类,还有创建一个例如MyBatisConfig类,里面存放applicationContext中特殊形式的的信息,比如起别名和扫描dao下所有接口的信息,单独存放在一个配置类中,不破坏已有架构文件的结构
MyBatisConfig类:
重点之一,里面方法上注解为Bean,就是在运行时会被扫描器所扫描到的方法
public class MyBatisConfig {
//消灭Xml文件(方法注解)--后续扫描
@Bean
public SqlSessionFactoryBean getSqlSessionFactory(@Autowired DataSource dataSource){
SqlSessionFactoryBean ssfb=new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.dou.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
MapperScannerConfigurer msc=new MapperScannerConfigurer();
msc.setBasePackage("com.dou.dao");
return msc;
}
}
然后就是SpringConfig配置类(特别重要):
这里设置为主配置类,因为写的东西特别少,所以里面并没有什么东西,在后续的开发中,如果需要什么配置可以直接填充,很方便.
//设置纯注解格式--设置当前类为spring核心配置加载类,其他次要第三方类直接集合形式导入
@Configuration
//bean扫描注解,扫描路径看仔细,是最上层路径*(替代context扫描)
@ComponentScan("com.dou")
//加载properties文件,就是咱们常用的jdbc配置文件
//这个东西可以引入,或者直接建一个config配置类导入,下面就是用的直接导入import
/*@PropertySource("classpath:jdbc.properties")*/
@Import({JDBCConfig.class,MyBatisConfig.class})
public class SpringConfig {
}
三层架构包
跟基础型开发差不多,多理解就感觉一毛一样,直接贴代码了
3.dao层
AccountDao类
public interface AccountDao {
@Insert("insert into spring (id,name,money) values(#{id},#{name},#{money})")
void save(Account account);
@Delete("delete from spring where id = #{id}")
void delete(Integer id);
@Update("update spring set name=#{name},money=#{money} where id=#{id}")
void update(Account account);
@Select("select * from spring")
List<Account> findAll();
@Select("select * from spring where id=#{id}")
Account findById(Integer id);
}
4.service层
包括service接口和service实现类,一毛一样
AccountService接口
public interface AccountService {
void save(Account account);
void delete(Integer id);
void update(Account account);
List<Account> findAll();
Account findById(Integer id);
}
Impl包下的业务实现类AccountServiceImpl
//component同样适用 设置该类为spring管理的bean
@Service("accountService")
public class AccountServiceImpl implements AccountService {
//设置对应属性的对象(或对方法)进行引用类型注入,以前用set注入,现在不需要了(参数)
@Autowired
private AccountDao accountDao;
public void save(Account account) {
accountDao.save(account);
}
public void update(Account account){
accountDao.update(account);
}
public void delete(Integer id) {
accountDao.delete(id);
}
public Account findById(Integer id) {
return accountDao.findById(id);
}
public List<Account> findAll() {
return accountDao.findAll();
}
}
5.还是实现一下
实现类中原本是用ClassPathXmlApplicationContext加载xml配置文件,现在注解形式不需要xml文件,直接加载主要配置类文件SpringConfig,使用AnnotationConfigApplicationContext加载
public static void main(String[] args) {
//xml配置加载ClassPathXmlApplicationContext
/* ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService= (AccountService) ctx.getBean("accountService");
Account ac = accountService.findById(1);
System.out.println(ac);*/
//配置文件类SpringConfig加载*(纯注解格式文件加载,跟加载xml配置文件不一样,为AnnotationConfigApplicationContext)
ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
AccountService accountService= (AccountService) ctx.getBean("accountService");
//剩下的这是功能实现
//方法实现:
//查看
List<Account> all1 = accountService.findAll();
System.out.println(all1);
//保存
Account account = new Account(2,"张飞",33.3);
accountService.save(account);
//单个查看
Account ac1 = accountService.findById(2);
System.out.println(ac1);
//修改4,名字变成寒蝉
account.setName("寒蝉");
accountService.update(account);
//单个查看
Account ac2 = accountService.findById(2);
System.out.println(ac2);
//删除
accountService.delete(2);
//查看
List<Account> all2 = accountService.findAll();
System.out.println(all2);
}
}
注解结束!!感谢我自己,谢谢谢谢,又浪费了时间,谢谢你
Aop开发
Aop开发好处很明显,解耦,减少内存使用,每段代码只需要把特有功能添加上去就可以了,公共功能可以设置before、after使用,也可以添加异常输出等等…也可以设置around,按源代码顺序去实现,
1.依赖添加
只需要在pom.xml中添加一个Aop依赖就行了
<!--导入Aop坐标-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2.改写注解项目实现AOP
改写时候不需要修改任何注解时的代码,只需要添加共性功能就行,代码太少不需要抽取什么东西
重点:在主要配置类SpringConfig中添加一个注解@EnableAspectJAutoProxy,设置开启AOP注解驱动的支持
@Configuration
@ComponentScan("com.dou")
/*@PropertySource("classpath:jdbc.properties")*/
@Import({JDBCConfig.class,MyBatisConfig.class})
//设置当前类开启AOP注解驱动的支持,加载AOP注解--重点
@EnableAspectJAutoProxy
public class SpringConfig {
}
3.添加AOP类
创建一个AOP的包,在里面添加aop方法
在AOP包下创建一个类RunTimeMonitorAdvice
//主--设置该类为spring管理的bean
@Component
//设置当前类为切面类
@Aspect
public class RunTimeMonitorAdvice {
//切入点,监控业务层接口,Service结尾方法
@Pointcut("execution(* com.dou.service.*Service.*(..))")
public void pt(){}
//所有注解必须加pt()方法,不然默认无切入
//业务模块代码执行之前执行
@Before("pt()")
public void before(){
System.out.println("有业务我就开始");
}
//该注解标注的方法在业务模块代码执行之后执行
//@AfterThrowing这个差不多的是报错执行,不写了
@AfterReturning("pt()")
public void afterreturning(){
System.out.println("这个业务代码执行完了");
}
//在所有的Advice执行完成后执行,类似finally
@After("pt()")
public void after(){
System.out.println("这个执行完了");
}
//环绕通知,用于调用业务模块的代码,--重点,切入是一个一个方法切入,不是一次全部方法切入
// 无论是调用前逻辑还是调用后逻辑,都可以在该方法中编写,
// 甚至其可以根据一定的条件而阻断业务模块的调用;
@Around("pt()")
public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {
//获取执行签名信息
Signature signature = pjp.getSignature();
//通过签名获取执行类型(接口名)
String className = signature.getDeclaringTypeName();
//通过签名获取执行操作名称(方法名)
String methodName = signature.getName();
//这行代码是重点,调用业务层方法进行执行,没有它就没有新世界
Object ret = pjp.proceed(pjp.getArgs());
System.out.println(ret);
//执行时长累计值
long sum = 0L;
//获取操作前系统时间beginTime
long startTime = System.currentTimeMillis();
/*//原始操作调用--傻帽操作,谁写的
pjp.proceed(pjp.getArgs());*/
//获取操作后系统时间endTime
long endTime = System.currentTimeMillis();
sum += endTime-startTime;
//打印信息
System.out.println(className+":"+methodName+"执行时间run:"+sum+"ms");
return ret;
}
}
@before和@after他们是内部执行
App的main方法输出是在最最后的,不要搞混了