
JAVA框架
JAVA框架
- Spring
- Spring进阶
- SpringMVC
- Mybatis
- Mybatis进阶
- Maven
- SpringBoot
- Dubbo
- Quartz
- 框架整合
- Spring-MyBatis整合
- Spring-SpringMVC-MyBatis整合
- Springboot-JSP整合
- Dubbo-SSM整合
- Spring-Redis整合
- Spring-Quartz整合
Spring是一个基于IOC和AOP的结构J2EE系统的框架,对象的生命周期由Spring来管理 IOC(Inversion Of Control):控制反转 DI(Dependency Inject): 依赖注入 AOP(Aspect Oriented Program):面向切面编程(实现周边功能,比如性能统计,日志,事务管理等) 方法: 新建对象的set和get方法 新建bean configuration … - applicationContext.xml、并在这个xml配置文件(SpringIOC容器)中使用Bean创建对象并且给对象及其属性赋值
<bean id="id(唯一)" class="包名.类名"> <property name="属性名" value="属性值" /> <property name="属性名" ref="属性映射(对应对象的id值)" /> </bean>然后通过主函数中 ApplicationContext取出对象
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 类 实例名 = (类名) context.getBean("id");三种依赖注入方式:set方法注入(同上)、构造方法注入( < constructor-arg value(ref)=“value” type=“type” index=“0” name=“属性名”>< /constructor-arg>)、p命名空间注入(引入p命名空间、简单类型:p:属性名=“属性值”、引用类型(除了String外):p:属性名-ref=“引用的id”) IOC容器赋值:如果是简单类型(8个基本+String),value; 如果是对象类型,ref=“需要引用的id值”,因此实现了对象与对象之间的依赖关系、赋值null< property name=“name” > < null/>< /property>、赋值空值< property name=“name” > < value>< /value> < /property>、集合类型赋值proprety中使用< set> < list> < array>等,可以混着用。注意< map> 中使用< entry> < key>< value> value与< value>注入方式的区别:value必须使用双引号,不能使用type属性,只能采用实体引用处理特殊符号,后者可以使用<![CDATA[ ]]>标记处理特殊符号 自动装配:bean中的autowire只适用于ref类型,autowire=“byName|byType|constructor|no”、实现全局自动装配default-autowire=“byName|by…”、注解形式的自动装配@Autowired、默认是byType、 @Qualifier(“id”)、改为byName 使用注解: ApplicationContext中增加扫描包
< context:component-scan base-package="包名"> </ context:component-scan>对应包中加入注解:@Component(“id”)细化:(dao层注解:@Repository)(service层注解:@Service)(控制器层注解:@Controller) 使用注解实现声明式事务:实现数据库的事务 配置:配置数据库相关、配置事务管理器txManager、增加对事务的支持;使用:方法明前增加注解@Transactional并增加其属性和方法 AOP:前置通知、后置通知、环绕通知、异常通知 实现方式:实现类、实现接口、注解、配置 接口形式AOP:实现接口并重写方法(前置MethodBeforeAdvice)(后置AfterReturningAdvice)(环绕MethodInterceptor)(异常ThrowsAdvice)、 ApplicationContext中加入业务类方法的对象和通知类方法的对象、增加配置:
< aop:config> <!-- 切入点(连接线的一端:业务类的具体方法) --> < aop:pointcut expression="execution(public * 业务类名.方法名(参数类型))" id="poioncut"/> <!-- (连接线的另一端:通知类) --> < aop:advisor advice-ref="通知类名" pointcut-ref="poioncut" /> </aop:config>环绕通知:可以获取目标方法的全部控制权,目标方法的一切信可以通过invocation参数获取到,底层是通过拦截器实现的、环绕通知类实现MethodInterceptor接口和invoke方法, result = invocation.proceed() ;中result获得返回值,invocation.proceed()实现业务类方法执行,try中实现前置通知和后置通知、catch中捕获异常并实现异常通知 注解形式AOP:@Component引入注解识别@Aspect修饰类形成通知类 @Before(pointcut=“execution(public * 业务类名.方法名(参数类型))”)修饰方法形成通知前置方法、后置@AfterReturning(returning=“returningValue”)、异常@AfterThrowing(throwing=“e”)、环绕@Around、方法中的参数可以使用JoinPoint jp、返回值参数Object returningValue、返回异常参数NullPointerException e、环绕通知中参数使用ProceedingJoinPoint jp 配置:增加扫描包、开启AOP注解代理< aop:aspectj-autoproxy>< /aop:aspectj-autoproxy> 配置形式AOP:写通知类logSchema及其通知方法,并将通知类和业务类加入到IOC容器中,applicationContext配置:
<aop:config> <!-- 切入点(连接线的一端:业务类的具体方法) --> <aop:pointcut expression="" id="pcShema"/> <!-- 原方法(连接线的另一端:通知类)<aop:advisor advice-ref="logSchea" pointcut-ref="pcShema" />--> <!-- schema方式 --> <aop:aspect ref="logSchema"> <!-- 连接线:连接业务和通知before --> <aop:before method="before" pointcut-ref="pcShema"/> <!-- 连接线:连接业务和通知afterReturning --> <aop:after-returning method="afterReturning" returning="returnValue" pointcut-ref="pcShema"/> <!-- 连接线:连接业务和通知Exception --> <aop:after-throwing method="Exception" pointcut-ref="pcShema" throwing="e"/> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pcShema" /> </aop:aspect> </aop:config>WEB项目整合Spring: IOC初始化:当服务启动时(tomcat),通过监听器将SpringIOC容器初始化一次(该监听器 spring-web.jar已经提供)web.xml配置、推荐方法:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml, <!--.默认约定的位置:WEB-INF/applicationContext.xml--> classpath:applicationContext-*.xml </param-value> </context-param>将applicationContext分层:cotroller、service、dao并分别实例化和依赖注入 实现Web容器和IOC容器的整合(手动方式):从IOC容器中求出实例对象、一般在servlet初始化中实现
public void init() throws ServletException { //ApplicationContext context= new ClassPathXmlApplicationContext("applicationContext-Service"); ApplicationContext context=WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); studentService=(IStudentService)context.getBean("studentService"); <!--类 实例名 = (类名) context.getBean("id");--> }最后完善web项目
Spring进阶注解形式存放bean: (配置类)必须有@Configuration注解
//存bean @bean //取bean ApplicationContext context = new AnnotationConfigApplicationContext(配置类.class) ;三层组件:(@Controller、@Service、@Repository -> @Component)+配置文件或者注解扫描器@component-scan(只对三层组件负责)、扫描器指定规则(FilterType(ANNOTATION,ASSIGNABLE_TYPE,CUSTOM)) 非三层组件(转换器): @Bean+方法的返回值、@import(直接编写到@Import中且id值是全类名、——自定义ImportSelector接口的实现类,通过selectimports方法实现(方法的返回值就是要纳入IoC容器的Bean),并且告知程序自己编写的实现类@Import({Orange.class,MyImportSelector.class})、——编写ImportBeanDefinitionRegistrar接口的实现类,重写方法 @Import({Orange.class,MyImportSelector.class,ImportBeanDefinitionRegistrar.class})并且告知程序自己编写的实现类)、FactoryBean(工厂Bean、准备bean实现类和重写方法,注册bean注册到@Bean中) bean的作用域:scope(singleton)单例默认值、@scope(prototype)多实例(singleton:容器在初始化时,就会创建对象(唯一的一个),支持延迟加载@Lazy、prototype:容器在初始化时,不创建对象;只是在每次使用时创建对象) 条件注解:可以让某一个Bean在某些条件下加入Ioc容器,其他情况下不加入容器,通过实现condition接口 Bean的生命周期:创建(new …)、初始化(赋初值)、 …、销毁 @Bean+返回值方式
@Bean(value="stu",initMethod = "myInit",destroyMethod = "myDestroy")三层组件功能性注解方式:将响应组件加入@Component(value="")注解、 给初始化方法加@PostConstruct、给销毁方法加@PreDestroy 三次组件接口方法:InitializingBean初始化、DisposableBean 销毁并实现其中的方法 接口BeanPostProcessor:拦截了所有中容器的Bean,并且可以进行bean的初始化 、销毁 BeanFactoryPostProcessor:bean被实例化之前 BeanDefinitionRegistryPostProcessor:bean被加载之前 具体顺序:BeanDefinitionRegistryPostProcessor(a) ->加载bean->BeanFactoryPostProcessor(b)->实例化bean->BeanPostProcessor 自动装配 @Autowired根据类型自动注入、结合@Qualifier("")根据名字注入、默认值@primary、@Autowired(required=false)修改未匹配为null 三层组件:如果@Autowired在属性前标注则不调用set方式;如果标注在set前面则调用set方式;不能放在方法的参数前 Bean+返回值:@Autowired可以在方法的参数前(也可以省略)、方法前(如果只有一个有参构造方法则@Autowired也可以省略) @Resource根据名字自动注入,没有名字然后根据类型 @Inject默认根据类型匹配(引入jar包) 底层组件:实现Aware的子接口,从而获取到开发的组件对象,对对象进行操作 环境切换:bean前@Profile说明条件注入 激活 1.运行环境中设置参数-Dspring.profiles.active=@Profile环境名 2.硬编码:IoC容器在使用时必须refresh(),需要设置保存点|配置类的编写处
//注解方式 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext() ; ConfigurableEnvironment environment = (ConfigurableEnvironment)context.getEnvironment(); environment.setActiveProfiles("@Profile环境名"); //保存点 context.register(配置类名.class); context.refresh();监听器:可以监听事件,监听的对象必须是ApplicationEvent自身或其子类/子接口 1.监听类实现ApplicationEvent接口 2.监听类注解形式申明是监听方法
@Component public class MyListener { //本方法是一个监听方法 @EventListener(classes = {ApplicationEvent.class}) public void myListenerMethod(ApplicationEvent event){ System.out.println("--0000000--------"+event); } } SpringMVCSpringMVC构建Web应用程序的全功能MVC模块 配置与使用: JSP发出请求 将Servlet的访问通过web.xml配置文件拦截请求,交给SpringMVC处理、快速创建:alt+/ dispatcherServlet
<!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--默认路径/WEB-INF/springDispatcherServlet-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>springmvc.xml中配置扫描包和视图解析器(用于解析返回值地址并通过请求转发实现页面跳转)
<!--配置视图解析器(InternalResourceViewResolver) --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/views/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--view-name会被视图解析器加上前缀和后缀 -->控制器中添加注解@controller(实现扫描包扫描)@RequestMapping(映射匹配类、类之前)、@RequestMapping(value,method,params)(映射匹配方法、方法之前)(可以增加个属性和约束条件对请求参数进行约束)、@PathVariable获取动态参数 REST风格:GET :查、POST :增、DELETE :删、PUT :改 springmvc实现给普通浏览器增加 put|delete请求方式 :put|post请求方式的步骤: 1.web.xml增加HiddenHttpMethodFilte过滤器
<filter> <filter-name>HiddenHttpMethodFilte</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilte</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>2.表单提交必须是post方法且通过隐藏域的value值设置实际的请求方式DELETE|PUT (< input type=“hidden” name="_method" value=“DELETE”/>) 3.控制器实现提交方式约束匹配、参数获取和功能执行 处理数据模型:跳转时需要带数据和页面(ModelAndView、ModelMap、Map、Model -数据放在了request作用域) ModelAndView:
public ModelAndView testModelAndView() { ModelAndView mv = new ModelAndView("jsp"); mv.addObject("属性名", 属性值或对象); return mv;}ModelMap:
public String testModelMap(ModelMap mm) { mm.put("属性名", 属性值或对象); return "jsp";}Map:
public String testMap(Map<String,Object> m) { m.put("属性名", 属性值或对象); return "jsp";}Model:
public String testMode(Model model) { model.addAttribute("属性名", 属性值或对象); return "jsp";}@SessionAttributes(value\\type):实现将数据放在request中的同时也将数据放在session中 @ModelAttribute:通过@ModelAttribute修饰的方法,会在每次请求前先执行;并且该方法的参数map.put()可以将对象放入即将查询的参数中,可以进行属性值的修改 视图的顶级接口:Views 视图解析器的顶级接口:ViewsResolver 国际化:针对不同地区、不同国家进行不同的显示 (创建资源文件、配置springmvc.xml并加载资源文件、通过jstl使用国际化)
<!--加载国际化资源文件--> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean>请求方法改变:return “redirect:/views/success.jsp”; 直接跳转(不通过控制器):< mvc:view-controller path=“handle/a” view-name=“success” /> < mvc:annotation-driven></ mvc:annotation-driven> 静态资源访问:(MVC交给Servlet处理)加入配置:
<!--该注解会让springmvc:接收一个请求,并且该请求没有对应@requestmapping时,将该请求交给服务器默认的servlet去处理(直接访问)--> <mvc:default-servlet-handler></mvc:default-servlet-handler> <mvc:annotation-driven></mvc:annotation-driven>类型转换:Spring自带一些常见的类型转换器、自定义类型转换器MyConverter(编写自定义类型转换类并引入接口Converter、配置将MyConverter加入到springmvc中、测试转换器)@RequestParam(“name”)是触发转换器的桥梁 格式化:springMVC配置数据格式化注解所依赖的bean+通过注解使用@DateTimeFormat(pattern=“yyyy-MM-dd”)@NumberFormat(parttern="###,#") 、错误消处理(参数BindingResult result返回前面参数的错误信,可以放在map里面传递到前端打印)、数据检验:JSR303和Hibernate Validator(jar包+配置(自动加载一个LocalValidatorFactoryBean类)+注解(给校验的对象前增加@Valid)) JSON:@ResponseBod修饰的方法,会将该方法的返回值以一个json数组的形式返回给前台 文件上传:配置MultipartResolver将其加入springIOC容器(可以设置属性)、处理方法中(参数@RequestParam(“file”) MultipartFile file获取前端传过来的文件数据)根据IO方法写输入输出流 拦截器:原理和过滤器原理相同(编写拦截器实现HandlerInterceptor接口、处理请求响应和渲染过程+将自己写的拦截器配置到springmvc中(< mvc:interceptor>)) 异常处理:如果一个方法用于处理异常,并且只处理当前类中的异常:@ExceptionHandler({Exception.class});如果一个方法用于处理异常,并且处理所有类中的异常: 类前加@ControllerAdvice、 处理异常的方法前加@ExceptionHandler;自定义异常显示页面@ResponseStatus; 通过配置实现的异常处理:SimpleMappingExceptionResolver
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 如果发生异常,异常对象会被保存在 exceptionAttribute的value值中;并且会放入request域中;异常变量的默认值是exception--> <!--<property name="exceptionAttribute" value="exception"></property>--> <property name="exceptionMappings"> <props> <!-- 相当于catch(ArithmeticException exception){ 跳转:error页面 } --> <prop key="java.lang.ArithmeticException">error</prop> <prop key="java.lang.NullPointerException">error</prop> </props> </property> </bean> MybatisMybatis可以简化JDBC操作和实现数据的持久化 ORM:Object Relational Mapping开发人员 像操作对象一样操作数据库表 SqlSessionFactory -> SqlSession ->StudentMapper ->CRUD 配置与使用 引入mybatis-jar包和数据库jar包 配置mybatis conf.xml:配置数据库信和需要加载的映射文件(运行环境默认是development、可以通过build的第二参数指定数据库环境)
PUBLIC "-//mybatis//DTD Config 3.0//EN" "mybatis/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!--如果使用的事务方式为jdbc,则需要手工commit提交,即sessionmit()--> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>表 - 类 映射文件xxMapper.xml :增删改查标签< select>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" "mybatis/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.mybatis.example.BlogMapper"> <select id="selectBlog" resultType="Blog" parameterType="int> <!--parameterType:输入参数的类型,resultType:返回类型、输入参数parameterType 和输出参数resultType,在形式上都只能有一个、如果输入参数:是简单类型(8个基本类型+String)是可以使用任何占位符,#{xxxx}、如果是对象类型,则必须是对象的属性#{属性名}--> select * from Blog where id = #{id} </select> </mapper>测试类 session.selectOne(“需要查询的SQL的namespace.id”,“SQL的参数值”)
public static void main(String[] args) throws IOException { //加载MyBatis配置文件(为了访问数据库) Reader reader = Resources.getResourceAsReader("conf.xml") ; SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader) ; //session - connection SqlSession session = sessionFactory.openSession() ; String statement = "org.lanqiao.entity.personMapper.queryPersonById" ; Student person = session.selectOne( statement,1 ) ; System.out.println(person); session.close();mapper动态代理方式CRUD:省略掉statement,即根据约定直接可以定位出SQL语句 配置环境:mybatis.jar/ojdbc.jar、conf.xml、mapper.xml 新建类和方法实现接口必须遵循以下约定: 1.方法名和mapper.xml文件中标签的id值相同 2.方法的输入参数和mapper.xml文件中标签的parameterType类型一致 (如果mapper.xml的标签中没有parameterType,则说明方法没有输入参数) 3.方法的返回值和mapper.xml文件中标签的resultType类型一致(无论查询结果是一个还是多个(student、List< Student>),在mapper.xml标签中的resultType中只写 一个(Student);如果没有resultType,则说明方法的返回值为void) 4.namespace的值就是接口的全类名( 接口 - mapper.xml 一 一对应) 5.测试中使用
T t = session.getMapper(接口.class) ; 返回类 返回值 = t.接口中的方法(参数) ;//接口中的方法->SQL语句 StudentMapper studentMapper = session.getMapper(StudentMapper.class) ; studentMapper.方法();6.优化:将配置信单独放入db.properties文件中然后再动态引入、MyBatis全局参数在conf.xml中设置、设置别名 类型转换器(自定义):实现java类型和jdbc类型的相互转化 1.创建转换器:实现TypeHandler接口或者继承BaseTypeHandler 2.配置conf.xml< typeHandlers>和mapper.xml与类对应(resultMap可以实现类型转换和属性-字段的映射关系) 输入参数:parameterType(简单类型:8个基本类型+String、.对象类型)、取值方法(#{}、${}都可以获取对象值和嵌套类型对象)(不同之处:简单类型的标识符、#{}会给String类型加上单引号、#{}可以防止sql注入)、参数类型为HashMap(用map中key的值匹配占位符#{stuAge},如果匹配成功就用map的value替换占位符)、参数为多个数据(可以使用[arg3, arg2, arg1, arg0, param3, param4, param1, param2]、在接口中通过@Param(“sNo”) 指定sql中参数的名字) 输出参数:resultType、resultMap(实体类的属性、数据表的字段: 类型、名字不同时、除此之外:实体类属性和数据字段不匹配时可以使用resultType+HashMap)、(输出类型为简单类型、对象类型、集合类型(resultType依然写集合的元素类型)、hashmap类型(本身是一个集合,可以存放多个元素)) 输出参数为Hashmap
//根据@MapKey("stuNo")知道 Map的key是stuNo @MapKey("STUNO") //oracle的元数据(字段名、表名 )都是大写 HashMap<Integer,Student> queryStudentsByHashMap(); //程序根据select的返回值 知道map的value就是 Student , <select id="queryStudentsByHashMap" resultType="HashMap"> select stuNo ,stuName ,stuAge from student </select>储存过程:数据库新建储存过程、Mapper中使用CALL调用存储过程(通过statementType="CALLABLE"设置SQL的执行方式是存储过程、存储过程的输入参数需要通过HashMap来指定)、使用过程(通过hashmap的put方法传入输入参数的值、通过hashmap的Get方法获取输出参数的值。) 动态sql语句:where-if(只能处理第一个有效的and)
<select id="queryStuByNOrAWishSQLTag" parameterType="student" resultType="student" > select stuno,stuname,stuage from student <where> <!-- <if test="student有stuname属性 且不为null"> --> <if test="stuName !=null and stuName!='' "> and stuname = #{stuName} </if> <if test="stuAge !=null and stuAge!=0 "> and stuage = #{stuAge} </if> </where> </select>foreach:< foreach>迭代的类型:数组、对象数组、集合、属性(包括属性类)、(简单类型的数组:在mapper.xml中必须用array代替该数组、集合类型的数组:必须用list代替该集合、对象数组:必须用object代替该集合、使用时用对象.属性)
<select id="queryStudentsWithNosInGrade" parameterType="grade" resultType="student"> select * from student <where> <if test="stuNos!=null and stuNos.size>0"> <foreach collection="stuNos" open=" and stuno in (" close=")" item="stuNo" separator=","> #{stuNo} <!--此时stuNo为对象的属性,本身是一个集合--> </foreach> </if> </where> </select>refid:(提取并引用sql语句) trim:增删改中有效使用
//添加where并处理拼接sql中开头或结尾的第一个和最后一个and <trim prefix="where" prefixOverrides="and" suffixOverrides="and">关联查询:一对一(业务扩展类核心:用resultType指定类的属性包含多表查询的所有字段、resultMap:通过属性成员建立起对应关系,对象成员使用 association映射、javaType指定该属性的类型(一对一:association,一对多:collection))一对多:resultMap:通过属性成员建立起对应关系,对象成员使用 collection映射、ofType指定该属性中元素的类型 日志:通过日志信,详细的阅读mybatis执行情况 log4j.jar包、开启日志conf.xml、编写配置日志输出文件log4j.properties
<settings> <!-- 开启日志,并指定使用的具体日志 --> <setting name="logImpl" value="LOG4J"/> </settings>延迟加载:实现部分查找和懒加载 开启延迟加载conf.xml、配置mapper.xml(查询对象的sql是通过select属性指定的关联mapper,并且通过column指定外键名)、如果增加了mapper.xml,要修改conf.xml配置文件(将新增的mapper.xml加载进去)
<settings> <!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 关闭立即加载 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>查询缓存: 一级缓存:MyBatis默认开启一级缓存,如果用同样SqlSession对象查询相同的数据,则只会在第一次查询时向数据库发送SQL语句,并将查询的结果 放入到SQLSESSION中(作为缓存在);后续再次查询该同样的对象时,则直接从缓存中查询该对象即可(即省略了数据库的访问)、commit语句会清理数据库缓存 二级缓存:只要产生的Mapper对象来自于同一namespace,则这些对象共享二级缓存 conf.xml中配置二级缓存< setting name=“cacheEnabled” value=“true”/> mapper.xml中声明开启 < cache/> Mapper的对应类、对应类的父类和级联属性都要需要实现序列化接口Serializable 触发将对象写入二级缓存的时机为SqlSession对象的close()方法 禁用二级缓存:select标签中 useCache=“false” 清理二级缓存:select标签中 flushCache="true"或者 其他操作的commit(),不能用查询的commit(); ehcache二级缓存整合:jar包、编写ehcache配置文件 Ehcache.xml、Mapper.xml中开启
<cache type="org.mybatis.caches.ehcache.EhcacheCache"> <property name="maxElementsInMemory" value="2000"/> <property name="maxElementsOnDisk" value="3000"/> </cache>逆向工程:表、类、接口、mapper.xml四者密切相关,根据表生成其他三个 jar包:mybatis-generator-core.jar、mybatis.jar、ojdbc.jar 逆向工程的配置文件generator.xml 执行
public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException { //配置文件 File file = new File("src/generator.xml") ; List<String> warnings = new ArrayList<>(); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(file); DefaultShellCallback callBack = new DefaultShellCallback(true); //逆向工程的核心类 MyBatisGenerator generator = new MyBatisGenerator(config, callBack,warnings ); generator.generate(null); }增加conf.xml和db.properties文件 使用query by CriteriaQBC
Mybatis进阶数据库版本切换 conf.xml切换environment并配置Provider别名
<!-- 配置数据库支持类--> <databaseIdProvider type="DB_VENDOR"> <property name="MySQL" value="mysql" /> <property name="Oracle" value="oracle" /> </databaseIdProvider>mapper.xml写不同数据SQL语句,配置databaseId=“Provider别名”
<select id="queryStudentByNoWithONGL" parameterType="student" resultType="student" databaseId="oracle">注解方式 将sql语句写在接口的方法上@Select("") 将接口的全类名写入< mapper>,或者批量写入
<mappers> <!--以下可以将com.yanqun.mapper 包中的注解接口和xml全部一次性引入 --> <package name="com.yanqun.mapper" /> </mappers>增删改返回值可以是void、Integer、Long、Boolean,都不需要在mapper.xml中设置返回值类型 事务提交
//手动提交: sessionFactory.openSession(); sessionmit(); //自动提交:每个dml语句 自动提交 sessionFactory.openSession(true);自增语句
//mysql设置自增数据为Integer类型的null,设置返回的自增数据,实现回写 useGeneratedKeys="true" keyProperty="number" //oracle通过序列模拟实现(before和after方式)鉴别器 : 对查询结果进行分支处理: 如果是a年级则真名,如果b年级显示昵称,由于字段不一致需要在resultMap中写
<discriminator javaType="string" column="gname"> <case value="a" resultType="com.yanqun.entity.Student" > <result column="sname" property="stuName"/> </case> <case value="b" resultType="student"> <result column="nickname" property="stuName"/> </case> </discriminator>架构分析 接口层:广义接口(增删改查) 数据处理层:参数处理,sql解析与执行,处理结果 框架支撑层:事务管理,缓存机制,连接池管理 引导层:XML配置,注解方式 源码分析 获取SqlSessionFactory对象 (通过parseConfiguration()在configuration标签设置了properties、settings、environments等属性标签)(所有的配置信放在Configuration对象中)(解析所有的Mapper.xml文件(分析其中的增删改查标签)成MappedStatement对象并放在Configuration中)(SqlSessionFactory对象 ->DefaultSqlSessionFactory ->Configuration ->包含了一切配置信) 获取SqlSession对象 (根据不同的类型execType,产生不同的 Executorconfiguration.newExecutor(tx, execType) ->SimpleExecutor、通过装饰模式将刚才产生的executor包装成一个更加强大的executor:executor = (Executor) interceptorChain.pluginAll(executor)、返回DefaultSqlSession(configuration,executor,事务)) (SqlSession ->openSession()->openSessionFromDataSource()->DefaultSqlSession对象->执行SQL) 获取XxxMapper对象 (代理接口中的方法、mapper.xml中的< select>等标签)(SqlSession(configuration,executor,事务)、代理接口的对象(MapperInterface)、methodCache(存放查询缓存,底层是CurrentHashMap)) 执行< select>等标签中定义的SQL语句 (MyBatis底层在执行CRUD时 可能会涉及到四个处理器:处理对象ParameterHandler的处理器:StatementHandler、处理参数的处理器:ParameterHandler、类转化器处理器:TypeHandler、处理结果集的处理器:ResultSetHandler)(动态代理:MapperProxy对象、执行增删改查->MapperProxy/invoke()–>InvocationHandler :JDK动态代理接口)(实际调用增删改查的方法:mapperMethod.execute(sqlSession,args) )(处理增删改查方法的参数:method.convertArgsToSqlCommandParam(args))(boundSql :将我们写的SQL和参数值进行了拼接后的对象,即最终能被真正执行的SQL)(通过Executor执行sql语句、底层执行方法:PreparedStatement的execute()) 自定义插件 四大核心对象:都涉及到了拦截器用于增强并且包含了该增强操作 StatementHandler、ParameterHandler、ResultSetHandler、Executor 步骤 编写拦截器
//目標方法target Object target = invocation.getTarget(); //目标对象target的包装后的产物MetaObject MetaObject metaObject = SystemMetaObject.forObject(target); //metaObject.getValue获取参数 Object value = metaObject.getValue("parameterHandler.parameterObject"); //metaObject.setValue设置参数 metaObject.setValue("parameterHandler.parameterObject",2); //放行 Object proceed = invocation.proceed(); return proceed;编写签名注解
@Intercepts({ //@Signature(type = StatementHandler.class , method ="query",args = {Statement.class, ResultHandler.class}) @Signature(type = StatementHandler.class , method ="parameterize",args = {Statement.class}) })conf.xml配置
<plugins> <plugin interceptor="com.yanqun.my.interceptors.MyInterceptor"> <property name="name" value="zs"/> <property name="age" value="23"/> </plugin> </plugins>批量操作:预编译一次sessionFactory.openSession(ExecutorType.BATCH)、不推荐拼接SQL方式 分页插件:PageHelper 引入jar(jsqlparser-0.9.5.jar、pagehelper-5.1.8.jar) 配置conf.xml插件 执行PageHelper.startPage(当前页, 每页数据) 使用页面信(PageInfo、Page对象) 插件:Mybatis-Plus、通用Mapper
MavenMaven是一个基于Java平台的自动化构建工具–将java、js、jsp等各个文件进行筛选、组装,变成一个可以直接发布的项目 www.mvnrepository 清理:删除编译的结果,为重新编译做准备 编译:java->class 测试:针对于项目中的关键点进行测试,亦可用项目中的测试代码去测试开发代码; 报告:将测试的结果进行显示 打包:将项目中包含的多个文件 压缩成一个文件, 用于安装或部署:(java项目-jar、web项目-war) 安装:将打成的包放到本地仓库,供其他项目使用 部署:将打成的包放到服务器上准备运行 下载配置maven 使用maven mvn compile 只编译main目录中的java文件 mvn test 测试 mvn package 打成jar/war mvn install 将开发的模块放入本地仓库供其他模块使用(放入的位置是通过gav决定) mvn clean 删除target目录(删除编译文件的目录) 运行mvn命令必须在pom.xml文件所在目录 目录结构
-src --main 程序功能代码 --java java代码 --resources 资源代码、配置代码 --test 测试代码 --java --resources pom.xml 项目对象模型POM(项目对象模型):Maven工程的基本工作单元XML文件,包含了项目的基本信,用于描述项目如何构建,声明项目依赖
<groupId>域名翻转.项目名</groupId> <groupId>org.lanqiao.maven</groupId> <artifactId>子模块名</artifactId> <artifactId>HelloWorld</artifactId> <version>版本号</version> <version>0.0.1-SNAPSHOT</version>依赖 在maven项目中如果要使用一个当时不存在的Jar或模块,则可以通过依赖实现(例如依赖测试类)
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.0</version> <scope>test</scope> </dependency>依赖排除:
<exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> </exclusions>依赖关联: A.jar->B.jar->C.jar 要使 A.jar ->C.jar:当且仅当 B.jar依赖于C.jar的范围是compile 依赖原则:路径最短原则(防止冲突) 路径相同距离:同一个pom文件后覆盖前、不同pom文件前覆盖后 统一编号和版本:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <xx>版本号</xx> </properties> //使用动态版本 <version>${xx} </version>生命周期 clean lifecycle :清理 pre-clean、clean、post-clearn default lifecycle :默认(常用) site lifecycle:站点 pre-site、site、post-site site-deploy 继承 父->子工程,可以通过父工程 统一管理依赖的版本 父工程pom方式打包 在父工程pom中编写依赖
<dependencyManagement> <dependencies> <dependency>给当前工程继承父工程
<parent> <!-- 1加入父工程坐标gav --> <groupId>org.lanqiao.maven</groupId> <artifactId>B</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 2当前工程的Pom.xml到父工程的Pom.xml之间的相对路径 --> <relativePath>../B/pom.xml</relativePath> </parent>在子类中需要声明使用哪些父类的依赖
<dependency> <!-- 声明:需要使用到父类的junit(只需要ga) --> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>聚和 聚合可以将拆分的多个子工程合起来共同操作(前置关联工程的install操作) 新建总工程中配置:只能配置在打包为pom方式的maven中
<modules> <!--项目的根路径 --> <module>../Maven1</module> <module>../Maven2</module> </modules>配置完聚合之后,操作总工程会自动操作改聚合中配置过的工程 部署Web 新建Maven项目并打war包 pom中配置servlet-api
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency>补全路径名:webapp->WEB-INF->web.xml 实际开发中开发人员将自己的项目开发完毕后打成war包(package) 交给实施人员去部署
SpringBootspringboot可以快速开发微服务模块,springboot将各个应用/三方框架设置成了一个个“场景”startspring.io可以自动生成SpringBoot的文件项目 准备JAVA和MAVEN的环境、实现springboot开发工具、目录结构resources(static:静态资源(js css 图片 音频 视频) 、templates:模板文件(模版引擎freemarker ,thymeleaf;默认不支持jsp)、application.properties: 配置文件对端口号等服务端信进行配置) 注解: @SpringBootApplication:springboot的主配置类 @Configuration:表示“配置类”:该类是一个配置类 、自动纳入Spring容器(@Component) @EnableAutoConfiguration:使spring boot可以自动配置:spring boot在启动时,就会将该包及所有的子包全部纳入spring容器,会根据META-INF/spring.factories找到相应的三方依赖,并将这些依赖引入本项目、Xxx_AutoConfiguration会实现自动装配并给予默认值 @SpringBootConfiguration:自己代码的自动配置 @ConditionalOnXxx:当这些条件都满足时此配置自动装配生效(手工修改改 自动装配:XxxProperties文件中的prefix.属性名=value ) 配置文件: application.properties : k=v,或行内写法(k: v,[Set/List/数组] {map,对象类型的属性},并且 []可省,{}不能省) application.yml:k:空格v、通过垂直对齐指定层次关系、默认可以不写引号 (双引号会将其中的转义符进行转义) @Component:将此类型加入Javabean @ConfigurationProperties(prefix=“student”):根据前缀名实现该类型自动装配,同yml文件相匹配 @Autowired:自动装配从bean中取值 @Value(""):实现单个值注入,可以和全局配置文件实现互补 @Validated:开启jsr303数据校验的注解 @Test:此类型为测试类 @ImportResource(locations={“classpath:spring.xml”}):识别spring.xml配置文件 @bean:通过实现注解配置将此类型加入到bean中
| 注值 | 批量注入 | 单个 |
| 松散语法 | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303数据校验 | 支持 | 不支持 |
| 注入复杂类型 | 支持 | 不支持 |
多环境切换:配置环境切换和动态环境切换 配置文件的位置:properties的优先级要大于yml 外部文件和外部参数:Run configuration ,argumenets方式和命令控制行 日志:spring boot默认选用slf4j和logback、日志级别、日志信格式、日志输出路径 Web静态资源:静态资源的存放路径通过WebMvcAutoConfiguration类-addResourceHandlers()指定:/webjars/成静态资源存放目录: {“classpath:/META-INF/resources/”,“classpath:/resources/”,“classpath:/static/”,“classpath:/public/”}以上目录存放资源文件后,访问时不需要加前缀、欢迎页(任意一个静态资源目录中的Index.html)、Logo(任意一个静态资源目录中的favicon.ico)、自定义静态资源存放路径(spring.resources.static-locations=…) Web动态资源:默认不支持jsp、html等,但是推荐使用模板引擎thymeleaf(网页=模板+数据) 引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency>使用thymeleaf只需要将文件放入目录:“classpath:/templates/”; 文件的后缀: “.html”; thymeleaf的th指定方式和符号取值方式(usingthymeleaf文档)
DubboRPC(Remote Procedure Call):远程过程调用 SOA(Service-Oriented Architecture):面向服务架构 Dubbo中控制器和服务端分离 步骤:提供方服务器运行提供方提供的服务、注册中心发布服务、消费方订阅服务、注册中心推送服务、消费方向提供方调用服务 开发dubbo程序:准备环境(linux环境中的jdk及其环境变量和zookeeper)、服务方(引入依赖:pom.xml、接口及实现类@Service、补全WEB-INF/web.xml、配置spring:applicationContext.xml)、消费方(引入依赖:pom.xml改端口号、补全WEB-INF/web.xml、配置springmvc、编写控制器代码@Reference:用于访问服务方提供的服务代码)、监听器(下载incubator-dubbo-ops、打包war、在linux中的tomcat中运行)
Quartzquartz:定时执行、异步任务 任务:Job、触发器:定义时间、调度器:将任务和触发器 一一对应 步骤 引入jar包 新建类制定具体任务 新建类任务调用的实现继承Job接口并执行具体任务
public class PlanJob implements Job { MeetingService meetingService = new MeetingService(); //jobExecutionContext可以获取设置的各种参数值 @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { TriggerKey triggerkey = jobExecutionContext.getTrigger().getKey(); JobKey jobKey = jobExecutionContext.getJobDetail().getKey(); System.out.println("----"); System.out.println(triggerkey+"\\n"+jobKey); JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); List<String> infos = (List<String>)jobDataMap.get("infos"); System.out.println(infos); //存放 计划执行的任务... meetingService.calClassMeeting(); } }新建测试方法类(产生)
public class TestQuartz { //XxxBuilder ->withIdentity()-->Xxx public static void main(String[] args) throws SchedulerException, InterruptedException, ParseException { // PlanJob JobBuilder jobBuilder = JobBuilder.newJob(PlanJob.class);//PlanJob PlanJob PlanJob //产生实际使用的Job JobDetail jobDetail = jobBuilder.withIdentity("meeting Job", "group1").build(); //向Job的execute()中传入一些参数。。。 // JobDatMap JobDataMap jobDataMap = jobDetail.getJobDataMap(); List<String> names = Arrays.asList(new String[]{"zs","ls","ww"}); jobDataMap.put("infos",names); // 触发器(Trigger):时间规则 ,依赖2个对象(TriggerBuilder ,Scheduel) TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger(); triggerBuilder = triggerBuilder.withIdentity("meeting trigger", "group1"); triggerBuilder.startNow();//当满足条件时 立刻执行 // 2019-03-13 09:46:30 -- // 2019-03-13 09:46:45 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date start = sdf.parse("2019-03-13 09:46:30"); Date end = sdf.parse("2019-03-13 09:46:45"); // triggerBuilder.startAt(start); // triggerBuilder.endAt(end); //scheduelBuilder:定执行的周期(时机) // SimpleScheduleBuilder scheduelBuilder = SimpleScheduleBuilder.simpleSchedule(); // scheduelBuilder.withIntervalInSeconds(1) ;//每隔1秒执行一次 // scheduelBuilder.withRepeatCount(3) ;//重复执行3次 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("5,10,15,30,45 * * * * ? *"); //产生触发器 // SimpleTrigger trigger = triggerBuilder.withSchedule(ScheduleBuilder).build(); CronTrigger trigger = triggerBuilder.withSchedule(cronScheduleBuilder).build(); // 调度器(工厂产生调度器) SchedulerFactory secheduleFacotry = new StdSchedulerFactory(); //产生调度器 Scheduler scheduler = secheduleFacotry.getScheduler(); //通过调度器 将 任务 和 触发器一一对应 scheduler.scheduleJob(jobDetail,trigger) ; scheduler.start(); // scheduler.shutdown(true); } } 框架整合 Spring-MyBatis整合引入jar包 配置类-表对应 配置Spring配置文件(applicationContext.xml)
<!-- 加载db.properties文件 --> <bean id="config" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="locations"> <array><value>classpath:db.properties</value></array> </property> </bean> <!-- 引入service层的bean --> <bean id="studentService" class="org.lanqiao.service.impl.StudentServiceImpl"> <property name="studentMapper" ref="studentMapper"></property> </bean> <!-- 配置配置数据库信(替代mybatis的配置文件conf.xml) --> <bean id="dataSource" class="org.apachemons.dbcp.BasicDataSource"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </bean> <!-- 在SpringIoc容器中 创建MyBatis的核心类 SqlSesionFactory --> <bean id="sqlSessionFacotry" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- 加载mapper.xml路径 --> <property name="mapperLocations" value="org/lanqiao/mapper/*.xml"></property> </bean>配置mapper中的sql语句 使用Spring-MyBatis整合产物开发程序
使用:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); context.getBean("bean") ; Spring-SpringMVC-MyBatis整合引入jar包 配置类-表对应 配置Spring配置文件(applicationContext.xml):使用Spring整合MyBatis 编写springmvc配置文件:视图解析器、基础配置 配置mapper中的sql语句 配置Web配置文件
<!-- Web项目中,引入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> <!-- 整合SPringMVC --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-controller.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> Springboot-JSP整合新建boot项目war包 建立基本的web项目所需要的目录结构 webapps/WEB-INF(需要) webapps/WEB-INF/web.xml (不需要) webapps/index.jsp 创建tomcat实例并部署项目:如果是一个war包的spring boot项目,在启动服务器tomcat时,会自动调用ServletInitializer类中的configure方法,configure方法会调用spring boot的主配置类从而启动spring boot
Dubbo-SSM整合创建父工程(引入公共依赖、实体类POJO依赖、module子模块依赖、解决Maven内置tomcat打包不引入xml问题的代码) 创建实体类(实体类需要implements Serializable接口) 创建公共模块实现接口共用(引入实体类POJO依赖、提供公共接口) 创建dao层(映射文件mapper、动态代理接口mapper、spring文件application(加载db文件、配置数据库信、创建核心类sqlsessionfactory)、将核心类交给spring处理) 创建service层(补全WEB-INF/web.xml并拦截交给spring处理、pom依赖父工程+dao层+公共接口+tomcat代码、编写spring的application文件并顺带启动dao层spring的application、service的具体实现类) 创建显示web层(补全WEB-INF/web.xml并拦截交给springMVC处理、pom依赖父工程+公共接口+tomcat代码、编写控制器、配置sppringMVC) 其他: 在maven中引入一个 mvn中央仓库中不存在的Jar:将jar自己安装到本地mvn仓库:cmd命令(ojdbc7.jar为例):mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc7 -Dversion=10.2.0.5.0 -Dpackaging=jar -Dfile=f:\\ojdbc7.jar 解决Maven内置tomcat打包不引入xml问题:
# 在父工程pom.xml的<project>元素中加入 <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build> Spring-Redis整合建立java文件并引入jar包 指定连接 Redis 服务器的相关信redis.properties(实现分配连接池和线程) 在spring的applicationContext配置文件中配置连接池、连接工厂和操作模板,并把RedisUtil加入bean中 使用工具类和测试类进行Redis的访问和检测
Spring-Quartz整合引入jar包 创建实体类封装Job信 创建实体类调用的具体方法 创建测试方法初始化容器和开始执行 创建配置文件applicationContext.xml
<!--配置任务信--> <bean id="scheduleJobEntity" class="com.yanqun.entity.ScheduleJob" > <property name="jobId" value="j001"></property> <property name="jobName" value="任务1"></property> <property name="jobGroup" value="任务组1"></property> <property name="jobStatus" value="1"></property> <property name="cronExpression" value="5,10,30,50 * * * * ? *"></property> <property name="desc" value="描述..."></property> </bean> <!--配置job类信--> <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" > <property name="jobClass" value="com.yanqun.job.PlanJob"></property> <property name="jobDataAsMap"> <map> <entry key="scheduleJob"> <ref bean="scheduleJobEntity"></ref> </entry> </map> </property> </bean> <!-- cronTrigger触发器:定义时间规则 <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail" > </property> <property name="cronExpression" value="#{scheduleJobEntity.cronExpression}"> </property> </bean>--> <!--SimpleTrigger触发器--> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean" > <property name="repeatInterval" value="2000"></property> <property name="repeatCount" value="10"></property> <property name="startDelay" value="3"></property> <property name="jobDetail" ref="jobDetail" ></property> </bean> <!--配置调度器--> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger" /> </list> </property> </bean>