Java框架学习
Spring
Spring IOC
1. Spring开发步骤
1. 导入坐标
2. 创建Bean
3. 创建applicationContext.xml
4. 在配置文件中进行配置(<bean></bean>)
5. 创建ApplicationContext对象getBean(提供配置时的id)
* 注意:
1. jdk版本问题,需要在project structure和settings中对jdk版本进行选择和更改
2. idea有自带的maven,自己安装了后应改为自己的maven
3. 更换aliyun如果还是无法下载,可以自己下载后放入对应仓库中再进行reload project
4. dependency容易爆红
2. Spring配置文件
2.1 Bean标签基本配置
默认情况用反射调用无参构造创建对象,基本属性:id(唯一标识)、class(Bean的全类名)
2.2 Bean标签范围配置
scope:对象作用范围
* singleton:默认值,单例
* 当Spring核心文件(配置文件)被加载时,实例化配置的Bean实例,且一直存在直到容器销毁或应用卸载
* prototype:多例的
* 在调用getBean方法时实例化Bean,对象在使用中就活着,长时间不使用会被Java垃圾回收机制销毁
* request:web项目中,Spring创建一个Bean的对象,将对象存入request域
* session:web项目中,Spring创建一个Bean的对象,将对象存入session域
* global session:web项目中,应用在Portlet环境,如果没有Portlet环境那么global session相当于session
2.3 Bean生命周期配置
* init-method:指定类中初始化方法名称
* destroy-method:指定类中销毁方法名称
2.4 Bean实例化三种方式
* 无参构造方法
* 工厂静态方法
* 配置bean中的factory和factory-method属性
<bean id="userDao" class="xxx.xxx.xxxfactory" factory-method="xxx()"></bean>
* 工厂实例方法
* 配置两个bean
<bean id="factory" class="xxx.xxx.xxxfactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="xxx()"></bean>
2.5 Bean依赖注入
理解为何需要依赖注入:https://www.bilibili.com/video/BV1WZ4y1H7du?p=14
依赖注入(dependency injection):Spring框架核心IOC的具体实现
注入方式:
* 构造方法
* 配置bean
<bean id="userDao" class="com.dbettkk.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.dbettkk.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
* 注意:constructor-arg中的name属性是UserServiceImpl的构造方法的参数部分,而ref属性则是上面已经配置好的bean的id。
* set方法
* 配置bean
<bean id="userDao" class="com.dbettkk.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.dbettkk.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
* 注意:property中的name属性是UserServiceImpl的setXxx()方法的xxx部分,而ref属性则是上面已经配置好的bean的id。
* 也可以使用p命名空间进行简化,然后在bean中通过属性方式进行配置,同理p-xxx中的xxx是setXxx()方法的xxx而,属性的值则是上面所配置的bean的id值
* xmlns="http://www.springframework.org/schema/p"
* <bean id="userService" class="com.dbettkk.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>
依赖注入的数据类型:
* 普通数据类型
* 引用数据类型
* 集合数据类型
* list、map、property
* 如果是基本数据类型就是value或者不加ref的属性,如果是引用数据类型则用ref属性
* 例如配置Map<String, User>
<property name="userMap">
<map>
<entry key="1" value-ref="user"></entry>
</map>
</property>
* 其中key代表基本数据类型,如果Map的key是引用数据类型,则使用key-ref,value同理value/value-ref
2.6 引入其他配置文件(分模块开发)
* 实际开发中,因为需要配置的东西很多,全写一起不方便,可以拆分为多个配置文件applicationContext-xxx,然后在主配置文件中使用import进行引入
* <import resource="applicationContext-dao.xml"></import>
2.7 小结
<bean>标签
id属性:容器中Bean对象的唯一标识
class属性:要实例化的Bean的全限定名
scope属性:Bean作用范围,常用为singleton和prototype
<property>标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值(已经配置好的bean的id)
<list>标签
<map>标签
<properties>标签标签
<constructor-arg>标签
<import>标签:导入其他Spring的分文件
3. Spring相关API
3.1 ApplicationContext相关的继承体系
众多接口-抽象类-实现类
3.2 ApplicationContext的实现类
* ClassPathXmlApplicationContext
* 从类的根路径下加载配置文件
* FileSystemXmlApplicationContext
* 从磁盘路径加载配置文件(绝对路径)
* AnnotationConfigApplicationContext
* 使用注解配置容器对象时,使用此类创建spring容器,读取注解
3.3 getBean()方法使用
参数:
* id(String):可以获取多个id不同class相同的bean,不会发生冲突
* 字节码文件(Class):不用进行强转,如果有多个id不同class相同的bean则会报错
4. Spring配置数据源
4.1 数据源(连接池)的作用
* 提高程序性能
* 实例化数据源,初始化部分连接资源
* 使用连接资源时从数据源中获取
* 使用完毕后将连接资源归还给数据源
4.2 抽取jdbc配置文件
1. 代码中加载
* 使用ResourceBundle加载配置文件并获取到值后用dataSource进行配置即可
2. Spring配置文件中加载
1. 引入context命名空间和约束路径
2. 使用context:property-placeholder并设置locations属性为properties文件位置
3. 使用SPEL表达式${key}获取properties配置文件中key对应的值并给bean标签下的property标签的value值
<context:property-placeholder location="classpath:xx.properties"/>
<property name="xxx" value="${key}"/>
4.2 Spring配置数据源
Spring注解开发
1. Spring原始注解
* Spring原始注解主要是替代<Bean>配置
* @Component:使用在类上用于实例化Bean
* @Controller:使用在web层类上用于实例化Bean
* @Service:使用在Service层类用于实例化Bean
* @Repository:使用在dao层类用于实例化Bean
* 这三个和Component是一样的,只是具有语义,方便理解
* @Autowired:使用在字段上根据类型依赖注入 ref
* @Qualifier:结合@Autowired一起使用用于根据名称进行依赖注入
* @Resource:相当于@Autowired+@Qualified,根据名称进行依赖注入
* @Value:注入普通属性
* 可以使用SPEL表达式-@Value("${key}")
* @Scope:作用范围
* @PostConstruct:init-method
* @PreDestroy:destroy-method
* 使用注解开发时,需要在配置文件中进行组件扫描
* <context:component-scan base-package="com.dbettkk"/>
* base-package:基本包,扫描该包以及子包的注解,以便识别
* 注意:
* 使用注解开发,可以不用写set方法
* 如果Spring容器中直存在一种类型的Bean,则相应的属性可以不写@Qualifier,只写@Autowired,默认从Spring容器中进行匹配
* 如果想要按照名称进行匹配,则需要@Autowired+@Qualifier
* 也可以将两个注解替换为@Resource(name=""),值为@Qualifier的value
2. Spring新注解
* 非自定义的Bean的配置<bean>
* 加载properties文件的配置:<context:property-placeholder>
* 组件扫描的配置:<context:component-scan>
* 引入其他文件:<import>
新注解:
* @Configuration:用于指定当前类时一个Spring配置类,当创建容器时会从该类上加载
* @ComponentScan:用于指定Spring在初始化容器时要扫描的包,作用和<context:component-scan>一致
* @Bean:使用在方法上,标注将该方法的返回值,存储在Spring容器中
* @PropertySource:用于加载.properties文件中的配置
* @import:用于导入其他配置类
Spring集成Junit
1. 原始Junit测试Spring的问题
* 在每个测试中都需要两行代码来获取ApplicationContext对象和使用getBean()方法获取想要测试的对象,冗余
2. 解决方案
* 让SpringJunit负责创建Spring容器,但是需要将配置文件名称告诉它
* 将需要进行测试的Bean直接在测试类中进行注入
3. 集成Junit步骤
1. 导入Spring集成Junit的坐标
2. 使用@Runwith注解替换原来的运行期
* @RunWith(SpringJUnit4ClassRunner.class)
3. 使用@ContextConfiguration指定配置文件或配置类
* 配置文件直接写,配置类需要指定@ContextConfiguration(classes = {SpringConfiguration.class})
4. 使用@Autowired注入需要测试的对象
5. 创建测试方法进行测试
Spring AOP
Spring AOP 简介
1. AOP概念
面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
2. AOP作用及优势
* 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
* 优势:减少重复代码,提高开发效率,并且便于维护
3. AOP的底层实现
AOP的底层是通过Spring提供的动态代理技术实现的。运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,再去调用目标的uix的方法,完成功能的增强。
4. AOP的动态代理技术
* JDK代理:基于接口的动态代理技术
* cglib代理:基于父类的动态代理技术
5. JDK的动态代理
final Advice advice = new Advice(); // 获得增强对象
final Target target = new Target();
// 返回值就是生成的动态代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 目标对象的类加载器
target.getClass().getInterfaces(), // 目标对象相同的接口字节码对象数组
new InvocationHandler() {
// 调用代理对象的任何方法,实质执行的为invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.before();// 前置增强
method.invoke(target, args);// 执行目标方法
advice.after();
return null;
}
}
);
proxy.save(); // 调用代理对象的方法
6. cglib的动态代理
final Advice advice = new Advice(); // 获得增强对象
final Target target = new Target();
// 返回值就是生成的动态代理对象 基于cglib
// 1.创建增强器
Enhancer enhancer = new Enhancer();
// 2.设置父类 (目标)
enhancer.setSuperclass(Target.class);
// 3.设置回调
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
advice.before(); // 执行前置
Object invoke = method.invoke(target, args);
advice.after(); // 执行后置
return invoke;
}
});
// 4.生成代理对象
Target proxy = (Target) enhancer.create();
proxy.save();
7. AOP相关概念
* Target(目标对象):代理的目标对象
* Proxy(代理):一个类被AOP植入增强后,就产生一个结果代理类
* Joinpoint(连接点):所谓的连接点就是指那些被拦截到的点,spring中,这些点指的是方法,因为spring只支持方法类型的连接点——(可以被增强的方法称为连接点)
* Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义——(实际被增强的方法称为切入点)
* Advice(增强/通知):所谓通知/增强是指拦截到Jpinpoint之后所要做得事情就是通知
* Aspect(切面):是切入点和通知的结合
* Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AaspectJ采用编译期织入好肉类装载期织入——(就是将你的切点和增强结合的过程称为织入)
8. AOP开发明确的事项
1. 需要编写的内容
* 业务核心代码(目标类的目标方法)
* 切面类,切面类中有通知(增强功能方法)
* 配置文件中配置织入关系,即将哪些溶质与哪些连接点进行结合
2. AOP技术实现的内容
* Spring框架监控切入点方法的执行,一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象相应位置,将通知对应的功能织入,完成完整的代码逻辑运行。
3. AOP底层使用哪种代理方式
在spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
9. 小结
* aop:面向切面编程
* aop底层实现:基于JDK和Cglib的动态代理
* aop重点概念:
* Ponitcut(切入点):被增强的方法
* Advice(通知/增强):封装增强业务逻辑的方法
* Aspect(切面):切点+通知
* Weaving(织入):将切点与通知结合的过程
* 开发明确事项:
谁是切点(切点表达式配置)
谁是通知(切面类中的增强方法)
将切点和通知织入配置
基于XML的AOP开发
1. 快速入门
1. 导入AOP相关坐标
2. 创建目标接口和目标类(内部有切点)
3. 创建切面类(内部有增强方法)
4. 将目标类和切面类的对象创建权交给spring
5. 在applicationContext.xml中配置织入关系
* <aop:config><aop:aspect ref="切面类"><aop:before method="通知方法名称" pointcut="切点表达式"/></aop:aspect></aop:config>
6. 测试代码
2. XML配置aop详解
1. 切点表达式写法
* execution([修饰符] 返回值类型 包名.类名.方法名(参数))
* 访问修饰符可以不写
* 返回值类型、包名、类名、方法名可以使用'*'代表任意
* 包名和类名之间一个点.代表当前包下的类,两个点..代表当前包及其子包下的类
* 参数列表可以使用两个点..表示任意个数、任意类型的参数列表
2. 通知的类型
* <aop:通知类型 method="" pointcut="切点表达式"/>
* 前置通知:<aop:before>
* 后置通知:<aop:after-returning>
* 环绕通知:前置+后置-<aop:around>
* 异常抛出通知:<aop:after-throwing>
* 最终通知:<aop:after>
3. 切点表达式的抽取
当多个增强的切点表达式相同时,可以进行抽取<aop:pointcut>,在增强中使用pointcut-ref进行引用
<aop:aspect ref="myAspect">
<!--抽取切点表达式-->
<aop:pointcut id="myPointcut" expression="execution(public void com.dbettkk.aop.Target.save())"/>
<!--切面=切点+通知-->
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
<aop:around method="around" pointcut-ref="myPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>
<aop:after method="after" pointcut-ref="myPointcut"/>
</aop:aspect>
基于注解的AOP开发
1. 快速入门
1. 创建目标接口和目标类(内部有切点)
2. 创建切面类(内部有增强方法)
3. 将目标类和切面类的对象创建权交给spring
4. 在切面类中使用注解配置织入关系
5. 在配置文件中开启组件扫描和AOP的自动代理
<context:component-scan base-package="com.xxx"/>
<aop:aspectj-autoproxy/>
6. 测试代码
2. 注解配置AOP详解
1. 通知类型:语法-@通知注解("切点表达式")
* @Before
* @AfterReturning
* @After
* @Around
* @AfterThrowing
2. 切点表达式的抽取
抽取方式为在切面类内部定义方法,在该方法上使用@Pointcut注解定义切点表达式,然后在增强注解中进行引用。
@Before("pointcut()")// 配置前置增强
public void before(){
System.out.println("前置增强...");
}
@Pointcut("execution(* com.dbettkk.anno.Target.save(..))")
public void pointcut() {}
Spring JdbcTemplate基本使用
1. 概述
是spring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装。spring框架为我们提供了很多模板类。JdbcTemplate、HibernateTemplate、RedisTemplate、JmsTemplate
2. 开发步骤
1. 导入spring-jdbc和spring-tx坐标
2. 创建数据库表和实体
3. 创建JdbcTemplate对象
JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource);
4. 执行数据库操作
template.update(sql, params)
template.query(sql, Mapper, params) 查询多个对象
template.queryForObject(sql, Mapper/required Class, params)
3. Spring产生JdbcTemplate对象
<!--加载properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据源对象-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
4. 常用操作
CRUD
Spring的事务控制
编程式-调用api
声明式-配置文件
编程式事务控制相关对象
1. PlatformTransectionManager:该接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法
* getTransection(TransectionDefination defination) 获取状态
* commit
* rollback
注意:不同的Dao层技术则有不同的实现类。该接口只规定控制事务的方法
2. TransectionDefination:是事务定义的信息对象
* getIsolationLevel():获取事务隔离级别——五类
* getPropogationBehavior():获取事务的传播行为
* REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,则加入这个事务(默认值)
* SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式运行
...
* getTimeout():获取超时时间
* isReadOnly():是否只读
3. TransecionStatus:提供事务具体的运行状态
* hasSavePoint()
* isCompleted()
* isNewTransection()
* isRollbackOnly()
基于XML的声明式事务控制
1. 概念
采用声明的方式来处理事务,即在配置文件中声明,来代替硬编码的方式
作用:
* 不侵入开发的组件
* 在不需要事务管理的时候,只要在设定文件上修改一下即可
注意:底层就是AOP
2. 声明式事务控制的实现
* 谁是切点
* 谁是通知
* 配置切面
3. 切点方法的事务参数的配置
<tx:advice id="txAdvice" transection-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
其中<tx:method>代表切点方法的事务参数的配置
* name:切点方法名
* isolation:事务隔离级别
* propogation:事务传播型位
* timeout:超时时间
* read-only:是否只读
其他相关配置
<bean id=transactionManager" class="jdbc模板">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="切点表达式"/>
</aop:config>
4. 小结
* 平台事务管理器配置
* 事务通知的配置
* 事务aop织入的配置
基于注解的声明式事务控制
1. 注解配置声明式事务控制解析
1. 使用@Transectional在需要进行事务控制的类或者方法上进行修饰,注解可用的属性同xml配置。且在类上使用该注解表示该类下的所有方法都是以同一套参数配置
2. XML配置文件中要开启事务的注解驱动<tx:annotation-driven/>
2. 知识要点
* 平台事务管理器配置(xml方式)
* 事务通知的配置(@Transectional注解配置)
* 事务注解驱动的配置<tx:annotation-driven/>
SpringMVC
Spring与Web环境的集成
1. ApplicationContext应用上下文获取方式
应用上下文是通过new ClassPathXmlApplicationContext(配置文件路径)获取的,但是每次写Servlet获得Bean都需要加载配置文件,存在弊端,加载多次。
在Web项目中可以使用ServletContextListener监听Web应用启动,在其启动时,加载配置文件,创建ApplicationContext对象,将其存储在最大的域servletContext域中,就可以在任意位置获取上下文对象了
2. Spring提供获取应用上下文的工具
上述分析不用动手实现,Spring提供了监听器ContextLoaderListener就是对上述功能的封装,还监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供工具类WebApplicationContextUtils供使用者获取应用上下文对象。
我们需要做的有两件事
* 在web.xml中配置COntextLoaderListener监听器(导入spring-web坐标)
* 使用WebApplicationContextUtils工具类获得上下文对象
SpringMVC的简介
1. SpringMVC概述
SpringMVC是基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架
SpringMVC已经称为目前最主流的MVC框架之一。通过一套注解,让简单的Java类称为处理请求的控制器,而无需实现任何接口,同时支持RESTful编程风格的请求
2. SpringMVC开发步骤
1. 导入SpringMVC包
2. 配置SpringMVC核心控制器DispatherServlet
3. 编写控制器(POJO-简单的JavaBean)和视图页面
4. 将Controller使用注解配置到Spring容器中(@Component,@Controller)
5. 配置spring-mvc.xml(组件扫描)
6. 执行访问测试
SpringMVC组件解析
1. SpringMVC执行流程
1. 用户发送请求至前端控制器DispatherServlet
2. DispatherServlet收到请求调用HandlerMapping处理器映射器
3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象以及处理器拦截器一并返回给DispatherServlet
4. DispatherServlet调用HandlerAdapter处理器适配器
5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
6. Controller执行完成后返回ModelAndView
7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatherServlet
8. DispatherServlet将ModelAndView传给ViewResolver视图解析器
9. ViewResolver解析后返回具体View
10. DispatherServlet根据View进行渲染视图(将模型数据填充至视图中)。DispatherServlet响应用户
2. SpringMVC注解解析
@RequestMapping:用于建立请求URL和处理请求方法之间的对应关系
位置:
* 类上:请求URL的以及访问目录,不写的话默认为应用的根目录
* 方法上:请求URL的第二级访问目录,与类上使用的@RequestMapping标注的以及目录一起组成访问虚拟路径
参数
* value:
* method:指定请求方式
* params:用于指定限制请求参数的条件,支持简单的表达式
* params = {"accountNmae"}:表示请求参数必须要accountName
* params = {"money!100"}:表示请求参数money不能是100
4. SpringMVC的xml配置解析
5. 知识要点
SpringMVC相关组件
* 前端控制器:DispatherServlet
* 处理器映射器:HandlerMapping
* 处理器适配器:HandlerAdapter
* 处理器:Handler
* 视图解析器:ViewResolver
* 视图:View
SpringMVC的注释和配置
* 请求映射注解:@RequestMapping
* 视图解析器配置:
REDIRECT_URL_PREFIX="redirect:"
FORWARD_URL_PREFIX="forward:"
prefix=""
suffix=""
<!--手动配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp"/>
<property name="suffix" value=".jsp"/>
</bean>
SpringMVC的数据响应
1. SpringMVC数据响应的方式
1. 页面跳转
* 直接返回字符串
* 通过ModelAndView对象返回
2. 回写数据
* 直接返回字符串
* 返回对象或集合
2. 页面跳转
1. 直接返回字符串形式
此方式会将返回的字符串与视图解析器的前后缀拼接后跳转
2. 返回ModelAndView对象
对ModelAndView对象进行添加视图和数据然后进行返回
3. 回写数据
1. 直接返回字符串形式
1. 通过框架注入的Response对象,使用response.getWriter().print()方法进行回写
2. 如果要直接返回字符串形式,因为框架会默认认为是页面跳转,所以需要通过@ResponseBody注解告知SpringMVC框架,方法返回的字符串不是跳转,而是直接在http响应体中返回
2. 回写对象或集合
为处理器适配器配置消息转换参数,指定使用jackson进行对象或集合的转换
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
mvc注解驱动
<mvc:annotation-driven/>
使用该驱动能默认底层实现jackson转换器
4. 知识要点
数据响应方式
1)页面跳转
2)回写数据
SpringMVC获得请求数据
1. 获得请求参数
* 基本类型参数
* POJO类型参数
* 数组类型参数
* 集合类型参数
2. 获得基本类型参数
Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配
3. 获得POJO类型参数
Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配
4. 获得数组类型参数
Controller中的业务方法的数组名称与请求参数的name一致,参数值会自动映射匹配
5. 获得集合类型参数
获得集合参数时,要将集合参数包装到一个POJO中才可以。
当使用ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装
6. 请求数据乱码问题
当post请求时,数据会出现乱码,我们可以设置一个过滤器来进行编码的过滤。
7. 参数绑定注解@RequestParam
当请求的参数名称与Controller的业务方法参数不一致时,需要通过@RequestParam注解显式的绑定
* value:与请求参数名称相同
* required:此在指定的请求参数是否必须包括,默认为true,没有参数则报错
* defaultValue:当没有指定请求参数式,则使用指定的默认值赋值
8. 获得Restful风格的参数
Restful是一种软件架构风格、设计风格,而不是标准,提供以组设计原则和约束条件,主要用于客户端和服务器交互类的软件,基于这个风格的设计的软件可以更简洁、有层次,更易实现缓存
Restful风格的请求是使用"url+请求方式"表示一次请求目的。
* GET
* POST
* PUT
* DELETE
在SpringMVC中可以使用占位符进行参数绑定,在业务方法中可以使用@PathVariable注解进行占位符的匹配获取工作
9. 自定义类型转换器
* SpringMVC默认提供一些常用的类型转换器
* 但不是所有数据类型都提供了转换器,没有提供的就需要自定义转换器
自定义类型转换的开发步骤
1. 定义转换器,实现Converter接口
2. 在配置文件中声明转换器
3. 在<annotation-driven>中引用转换器
10. 获得请求头
1. @RequestHeader:可获得请求头信息 相当于request.getHeader(name)
* value:请求头名称
* required:是否必须携带
2. @CookieValue:可以直接获得Cookie值
* value:指定cookie名称
* required:是否必须携带
11. 文件上传
文件上传客户端三要素
1. 表单项type="file"
2. 表单提交方式为post
3. 表单的enctype属性是多部分表单形式,及enctype="multipart/form-data"
文件上传原理
* 当form表单修改为多部分表单时,request.getParamter()将失效
* enctype="application/x-www-form-urlencoded"时,form表单的正文内容格式是:key=value&key=value
* 当form表单的enctype取值为Mutipart/form-data时,请求正文内容就变成多部分形式
12. 单文件上传步骤
1. 导入fileupload和io坐标
2. 配置文件上传解析器
3. 编写文件上传代码
13. 单文件上传实现
14. 多文件上传
页面上使用相同name的多个input项,在服务器端使用MultipartFile[]进行接收即可
SpringMVC拦截器
1. 拦截器interceptor的使用
SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理
将拦截器按一定的顺序连结成一条链,这条链称为拦截器链。在访问时,拦截器链中的拦截器就会按照配置的顺序调用,拦截器也是AOP思想的具体实现
2. 拦截器和过滤器区别
* 使用范围
Filter:任何JavaWeb工程都能使用
Interceptor:SpringMVC的一部分,只有使用框架的项目能使用
* 拦截范围
Filter:在url-pattern中配置了/*之后,可以对所有访问的资源进行拦截
Interceptor:只会拦截访问的控制器方法,如果访问的是jsp、html、css、img或者js是不会进行拦截的
3. 拦截器快速入门
自定义拦截器
1. 创建拦截器实现HandlerInterceptor接口
2. 配置拦截器
3. 测试拦截器的拦截效果
4. 拦截器方法说明
* preHandle():请求处理之前调用,返回类型为Boolean,true为放行
* postHandle():请求处理之后、视图返回前调用,可对ModelAndView对象进行操作
* afterCompletion():整个请求结束之后,渲染了视图之后
5. 案例-用户登录权限控制
需求:用户没有登录的情况下,不能对后台菜单进行访问,点击菜单跳转到登录页面
Spring练习 环境搭建
1. 环境搭建步骤
1. 创建工程
2. 导入静态页面
3. 导入需要坐标
4. 创建包结构
5. 导入数据库脚本
6. 创建POJO类
7. 创建配置文件
2. 角色列表的展示步骤分析
1. 点击角色管理菜单发送请求到服务器端
2. 创建RoleController和showList()方法
3. 创建RoleService和showList()方法
4. 创建RoleDao和findAll()方法
5. 使用JdbcTemplate完成查询操作
6. 将查询数据存储到Model中
7. 转发到role-list.jsp页面进行展示
3. 角色添加的步骤分析
1. 点击列表页面新建按钮跳转到角色添加页面
2. 输入角色信息,点击保存按钮,表单数据提交服务器
3. 编写RileController的save()方法
4. 编写RoleService的save()方法
5. 编写RoleDao的save()方法
6. 使用JdbcTemplate保存Role数据到sys_role
7. 跳转回角色列表界面
SpringMVC异常处理
1. 异常处理的思路
就两类异常 通过捕获异常或规范代码进行处理
系统的Dao、Service、Controller出现异常都进行抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理。
2. 异常处理的两种方式
* 使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver
* 使用Spring异常处理接口HandlerExceptionResolver自定义自己的异常处理器
3. 简单异常处理器SimpleMappingExceptionResolver
SpringMVC已经定义好,使用时,根据项目情况进行相应异常与视图的映射配置
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error"/>
<property name="exceptionMappings">
<map>
<entry key="java.lang.ClassCastException" value="error1"/>
<entry key="MyException" value="error2"/>
</map>
</property>
</bean>
4. 自定义异常处理步骤
1. 创建异常处理器实现HandlerExceptionResolver
2. 配置异常处理器
3. 编写异常页面
4. 测试异常跳转
MyBatis
MyBatis简介
1. 原始jdbc操作
2. 原始jdbc操作的分析
* 问题:
1. 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能
2. sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化可能较大,sql变动需要改变java代码
3. 查询操作,需要手动将结果集中的数据手动封装到试题中,插入操作时,需要手动将实体的数据设置到sql的占位符位置
* 解决方案
1. 使用数据库连接池初始化连接资源
2. 将sql语句抽取到xml配置文件中
3. 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射
3. 什么是Mybatis
* mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
* mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句
* 最后由mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc进行封装,屏蔽了jdbc api底层访问细节,使我们不用于jdbc api打交道就可以完成对数据库的持久化操作
MyBatis快速入门
1. Mybatis开发步骤
1. 添加Mybatis坐标
2. 创建user数据表
3. 编写User实体类
4. 编写映射文件UserMapper.xml(SQL语句)
5. 编写核心文件SqlMapConfig.xml(MyBatis核心配置)
6. 编写测试类
2. 环境搭建
3. 编写测试代码
4. 知识小结
MyBatis映射文件概述
<?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="userMapper">
<select id="findAll" resultType="com.dbettkk.domain.User">
SELECT * FROM user
</select>
</mapper>
MyBatis增删改查操作
1. 插入数据库操作
注意问题:
* 插入语句使用insert标签
* 在映射文件中使用parameterType属性指定要插入的数据类型
* Sql语句中使用#{实体属性名}方式引用实体中的属性值
* 插入操作使用的API是sqlSession.insert("命名空间.id", 实体对象)
* 插入操作设计数据库数据变化,所以要使用sqlSeesion对象显式的提交事务,即sqlSession.commit()
2. 更新操作
注意问题
* 使用update标签
* sql语句使用#{实体属性名}方式引用实体中的属性值
* 更新操作使用的API是sqlSession.update("命名空间.id", Object);
3. 删除操作
注意问题
* 使用delete标签
* sql语句使用#{任意字符串}方式引用传递的单个参数
* 删除操作使用的API是sqlSession.delete("命名空间.id", Object);
4. 知识小结
MyBatis核心配置文件概述
1. 核心配置文件层级关系
* configuration配置
* properties属性
* settings设置
* typeAllases类型别名
* typeHandlers类型处理器
* objectFactory对象工厂
* plugins插件
* environments环境
* environment环境变量
* transactionManager事务管理器
* dataSource数据源
* databaseProvider数据库厂商标识
* mappers映射器
2. 常用配置解析
1. enviroments标签:数据库环境的配置,支持多环境的配置 需指定默认环境
事务管理器类型有两种
* JDBC:直接使用JDBC的提交和回滚,依赖于从数据源得到的连接来管理事务作用域
* MANAGED:这个配置几乎没做什么,从不提交或回滚一个连接,它让容器来管理事务的整个生命周期(比如JEE应用服务器的上下文),默认情况下会关闭连接,需要配置相关属性。
数据源类型有三种:
* UNPOOLED:知识每次被请求时打开和关闭连接
* POOLED:这种数据源的实现利用池的概念将JDBC连接对象组织起来
* JDNI:这个数据源的实现是为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后防止一个JNDI上下文的引用
2. mapper标签:加载映射
* 使用相对于类路径的资源引用,例如<mapper resource="com/dbettkk/mapper/UserMapper.xml"/>
* 使用完全限定资源定位符(URL),绝对路径
* 使用映射器接口实现类的完全限定类名,例如<mapper class="全限定类名"/>
* 将包内的映射器接口实现全部注册为映射器,例如:<package name="包名"/>
3. properties标签:该标签可以加载额外配置的properties文件
* <properties resource="jdbc.properties"/>
4. typeAliases标签:定义别名
mybatis框架已经为我们设置好了一些常用类型的别名string、long、int、double、boolean
<typeAliases>
<typeAlias type="com.dbettkk.domain.User" alias="user"/>
</typeAliases>
MyBatis相应的API
1. SqlSession工厂构造器SqlSessionFactoryBuilder
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
// 加载核心配置文件
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得session工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);
// 获得session会话对象
SqlSession sqlSession = factory.openSession();
2. SqlSession工厂对象SqlSessionFactory
* openSession() 默认开启一个事务,该事务不会自动提交,需要手动提交
* openSession(boolean autoCommit) 设置参数 是否自动提交
3. SqlSession会话对象
insert、update、delete方法
<T> T selectOne()、<E> List<E> selectList()
rollback、commit方法
MyBatis的Dao层实现
1. 传统开发方式:接口和实现都需要编写
2. 代理开发方式:只需要编写Mapper接口
遵循以下规范
1. Mapper.xml文件中的namespace与mapper接口全限定名相同
2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType类型相同
InputStream stream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
通过接口来执行方法
MyBatis映射文件深入
1. 动态sql语句
动态sql <if>
动态sql <foreach>
2. sql片段抽取
将重复的sql片段进行抽取<include>和<sql>标签
3. 小结
<select><insert><update><delete> 增删改查
<where><if><foreach> if和foreach
<sql><include> sql片段抽取
MyBatis核心配置文件深入
1. typeHandler标签:类型处理器
可以重写或者自定义类型处理器,实现TypeHandler接口或继承BaseTypeHandler类
开发步骤
1. 定义转换类继承类BaseTypeHandler<T>
2. 覆盖四个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时mysql的字符串类型转换成java的Type类型的方法
3. 在MyBatis核心配置文件中注册
4. 测试
2. plugins标签:插件标签
分页助手插件 使用简单方式获得分页数据
还能获取相关的分页信息PageInfo<User> pageInfo = new PageInfo<User>(userList);
开发步骤
1. 导入统一PageHelper坐标
2. 在mybatis核心配置文件中进行配置
3. 测试分页数据获取
MyBatis的多表操作
1. 一对一查询
<resultMap id="orderMap" type="order">
<!--
手动指定字段与实体属性的映射关系
column: 字段名称
property: 属性名称
-->
<id column="oid" property="id"/>
<result column="ordertime" property="ordertime"/>
<result column="total" property="total"/>
<!--<result column="uid" property="user.id"/>
<result column="username" property="user.username"/>
<result column="password" property="user.password"/>
<result column="birthday" property="user.birthday"/>-->
<!--
property: 指当前实体(order)属性 的名称(user)
javaType: 指当前实体(order)属性 的类型(User)
-->
<association property="user" javaType="user">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="birthday" property="birthday"/>
</association>
</resultMap>
<select id="findAll" resultMap="orderMap">
SELECT *, o.id oid FROM orders o, user u WHERE o.uid = u.id
</select>
2. 一对多查询
<resultMap id="userMap" type="user">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="birthday" property="birthday"/>
<!--
配置集合属性
property: 集合名称
ofType: 集合中的数据类型
-->
<collection property="orderList" ofType="order" >
<!--封装order的数据-->
<id column="oid" property="id"/>
<result column="ordertime" property="ordertime"/>
<result column="total" property="total"/>
<!--<association property="user" javaType="user">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="birthday" property="birthday"/>
</association>-->
</collection>
</resultMap>
3. 多对多查询
和一对多类似 只有sql语句存在差别
4. 知识小结
配置方式
一对一:<resultMap>
一对多:<resultMap>+<collection>
多对多:<resultMap>+<collection>
MyBatis注解开发
1. MyBatis常用注解
* @Insert
* @Update
* @Delete
* @Select
* @Result:结果集封装
* @Results:多个结果集
* @One:实现一对一结果集封装
* @Many:实现一对多结果集封装
2. 注解实现复杂映射开发
使用后四个注解完成复杂关系的配置
@Results => <resultMap>
@Result
* column
* property
* one
* many
@One => <association>
* select:指定多表查询的sqlmapper
@Result(column="", property="",one=@One(select=""))
@Many => <collection>
* 指定子查询返回对象集合
@Result(column="", property="",many=@Many(select=""))
SSM框架整合
1. 原始方式整合
2. Spring整合MyBatis
前半部分 将session工程将给Spring容器管理 从容器拿出mapper使用
后半部分 事务控制由Spring的声明式事务控制管理
Docker
1. Docker进程相关命令
* 启动 systemctl start docker
* 停止 systemctl stop docker
* 重启 systemctl restart docker
* 查看 systemctl status docker
* 设置开机启动 systemctl enable docker
2. Docker镜像相关命令
* 查看镜像 docker images (-q) (-q查看所用镜像的id)
* 搜索镜像 docker search 镜像名称
* 拉取镜像 docker pull 镜像名称:镜像版本 # 可去dockerhub查看想要下载的版本
* 删除镜像
* docker rmi 镜像id(或者镜像名称)
* docker rmi `docker images -q` # 删除所有镜像
3. Docker容器相关命令
* 查看容器
* docker ps # 查看正在运行的容器
* docker ps -a # 查看所有容器
* 创建并启动容器 docker run 参数
* -i:保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,exit退出容器后,容器自动关闭。
* -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
* -d:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。
* -it 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器
* --name:为创建的容器命名。
* 进入容器 docker exe 参数
* 使用exit退出容器时 容器不会自动关闭
* 停止容器 docker stop 容器名称/容器id
* 启动容器 docker start 容器名称/容器id
* 删除容器 docker rm 容器名称/容器id # 如果容器为运行状态 则无法删除
* 查看容器信息 docker inspect 容器名称
4. 配置数据卷容器
* 创建启动c3数据卷容器,使用 –v 参数 设置数据卷
* docker run –it --name=c3 –v /volume ubuntu:16.04 /bin/bash
* 创建启动 c1 c2 容器,使用 –-volumes-from 参数 设置数据卷
* docker run –it --name=c1 --volumes-from c3 ubuntu:16.04 /bin/bash
* docker run –it --name=c2 --volumes-from c3 ubuntu:16.04 /bin/bash