SSM配置事务管理器
1.事务管理器配置模板(MySQL是8.0.15)
<!--配置C3P0连接池--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--注入里面的属性值-->
<property name="driverClass" value="com.mysql.cj.jdbc.Driver">
</property>
<property name="jdbcUrl" value="jdbc:mysql:///数据库名?serverTimezone=GMT%2B8&useSSL=false">
</property>
<property name="user" value="用户名">
</property>
<property name="password" value="密码">
</property>
</bean>
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入dataSource,指定对哪个数据库进行操作-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2.配置事务增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--做事务操作-->
<tx:attributes>
<!--设置进行事务操作的方法匹配规则-->
<!--以account开头的方法
propagation事务的隔离级别-->
<tx:method name="account*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--3.配置切面-->
<aop:config>
<!--切入点-->
<aop:pointcut id="pointcut1" expression="execution(* service.OrdersService.*(..))"/>
<!--切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
2.首个项目事务管理器配置
<!--事务管理器
对mybatis操作数据库事务控制,spring使用jdbc事务控制
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--数据源-->
<!--这里的数据源引用外部文件中dataSource-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--通知(增强)-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--propagation="REQUIRED":必须要事务的方法。name="save*":以save开头的方法-->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--aop-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* service.impl.*.*(..))"/>
</aop:config>
3.Spring的三大核心思想
(1)IOC(控制反转)、DI(依赖注入)
<!--singleton:scope的默认值,单例。prototype:多例-->
<!--类里面必需含有无参的构造方法-->
<bean id="user1" class="beans.User" scope="singleton">
</bean>
<!--使用有参构造方法注入属性-->
<bean id="user2" class="beans.User">
<constructor-arg name="username" value="小关">
</constructor-arg>
</bean>
<!--使用set方法注入属性-->
<bean id="user3" class="beans.User">
<!--name属性:类里面属性名
value属性:设置的值
-->
<property name="username" value="小韩">
</property>
</bean>
<!--使用P名称空间注入属性-->
<bean id="user4" class="beans.User" p:username="傻狗宝">
</bean>
<!--使用set方法注入对象类型的属性-->
<!--1.配置userService和userDao对象-->
<bean id="userDao" class="beans.UserDao">
</bean>
<bean id="userService" class="beans.UserService">
<!--注入UserDao对象
name属性:UserService类里面属性名
不写value属性,因为是对象
ref属性:配置UserDao的Bean标签的id
-->
<property name="userDao" ref="userDao">
</property>
</bean>
<!--注入复杂类型的属性-->
<bean id="user5" class="beans.User">
<!--数组-->
<property name="arrs">
<list>
<value>小王</value>
<value>小张</value>
<value>小华</value>
</list>
</property>
<!--list-->
<property name="list">
<list>
<value>大刘</value>
<value>大宋</value>
<value>大唐</value>
</list>
</property>
<!--map-->
<property name="map">
<map>
<entry key="a" value="lucy"></entry>
<entry key="b" value="tom"></entry>
<entry key="c" value="mary"></entry>
</map>
</property>
<!---->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
(2)AOP(面向切面编程)
1.非注解方式
<!--配置对象-->
<bean id="book" class="beans.Book"></bean>
<bean id="myBook" class="beans.MyBook"></bean>
<!--配置aop操作-->
<aop:config>
<!--配置切入点
execution()表达式
-->
<aop:pointcut id="pointcut1" expression="execution(* beans.Book.*(..))"/>
<!--配置切面
把增强用到方法上面
1.切入点:在类里面可以有很多的方法被增强,比如实际操作中,只是增强了类里面add方法,
实际增强的方法称为切入点
2.通知/增强:增强的逻辑,称为增强,比如扩展日志功能,这个日志功能称为增强
前置通知/增强:在方法之前执行
后置通知:在方法之后执行
异常通知:方法出现异常
最终通知:在后置通知之后执行
环绕通知:在方法之前和之后执行
3.切面:把增强应用到方法上面的过程称为切面
-->
<aop:aspect ref="myBook">
<!--配置增强类型
method:增强类里面使用哪个方法作为前置
-->
<!--前置增强-->
<aop:before method="before1" pointcut-ref="pointcut1"/>
<!--后置增强-->
<aop:after-returning method="after1" pointcut-ref="pointcut1"/>
<!--环绕增强-->
<aop:around method="around1" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
2.注解方式
<!--开启aop操作-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--配置对象-->
<bean id="book" class="beans.Book"></bean>
<bean id="myBook" class="beans.MyBook"></bean>
package beans;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class MyBook {
//在方法上面使用注解完成增强配置
@Before(value = "execution(* beans.Book.*(..))")
public void before1(){
System.out.println("前置增强!");
}
@AfterReturning(value = "execution(* beans.Book.*(..))")
public void after1(){
System.out.println("后置增强!");
}
//环绕增强
@Around(value = "execution(* beans.Book.*(..))")
public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//方法之前
System.out.println("方法之前!");
//执行被增强的方法
proceedingJoinPoint.proceed();
//方法之后
System.out.println("方法之后!");
}
}
4.SSM框架常用依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--日志生成依赖-->
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- 数据库驱动依赖 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--数据库连接池依赖-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>mchange-commons-java</artifactId>
<version>0.2.11</version>
</dependency>
<!--DAO层框架:MyBatis依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
</dependency>
<!--MyBatis整合Spring依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.3</version>
</dependency>
<!--jstl标签库依赖-->
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--json解析依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
<exclusions>
<exclusion>
<artifactId>jackson-annotations</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
<!--逆向工程依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<!--Spring核心依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--AOP依赖-->
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- Spring WEB依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--校验依赖-->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.0.CR2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!--文件上传依赖-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--<scope>provided</scope>-->
</dependency>
</dependencies>
5.异常java.lang.IllegalArgumentException: At least one base package must be specified处理方式之一
部分异常日志
[ERROR] Context initialization failed
java.lang.IllegalArgumentException: At least one base package must be specified
at org.springframework.util.Assert.notEmpty(Assert.java:214)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:245)
at org.mybatis.spring.mapper.ClassPathMapperScanner.doScan(ClassPathMapperScanner.java:164)
解决方法
错误原因:在mapper扫描器中忘记了设置value值(需要扫描包的路径),value值为空。
<!--配置MyBatis的sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据库连接池-->
<property name="dataSource" ref="dataSource"/>
<!--加载mybatis的全局配置文件-->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
</bean>
<!--mapper扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描包路径,如果需要扫描多个包,中间使用半角逗号隔开-->
<property name="basePackage" value=""/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
6.SpringMVC之validation校验
(1)校验理解
在项目中,通常使用较多的是前端校验,比如页面中js校验。对于安全要求较高的建议在服务端进行校验。
服务端校验:
(1)控制层controller:校验页面请求的参数的合法性。在服务端控制层controller校验,不区分客户端类型(浏览器、手机客户端、远程调用)
(2)业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。
(3)持久层dao:一般不校验
(2)SpringMVC校验
SpringMvc使用hibernate的校验框架validation(和hibernate没有任何关系)。
校验思路:页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
(3)环境配置
hibernate的校验框架validation所需依赖:
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.0.CR2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
(4)配置校验器
<!--校验器-->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!--指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties-->
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<!--检验错误信息配置文件-->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!--源文件名-->
<property name="basenames">
<list>
<value>classpath:CustomValidationMessages</value>
</list>
</property>
<!--资源文件编码格式-->
<property name="fileEncodings" value="utf-8"/>
<!--对资源文件内容缓存时间,单位秒-->
<property name="cacheSeconds" value="120"/>
</bean>
(5)在实体类中添加校验规则
public class Commodity {
private Integer id;
//校验名称在1到30字符之间
//message时提示校验出错显示的信息
@Size(min = 1,max = 20,message = "{commodity.name.length.error}",groups = {ValidGroup1.class})
private String cname;
private Double price;
//非空校验
@NotNull(message = "{commodity.createtime.isNull}")
private Date createtime;
(6)创建CustomValidationMessages.properties文件
#添加校验错误提交信息
commodity.name.length.error=请输入1到30个字符的商品名称
commodity.createtime.isNull=请输入商品的生产日期
(7)捕获并显示错误信息
/**
* 商品信息修改提交
* 在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息
* @Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的(一前一后)
* value = {ValidGroup1.class}指定使用ValidGroup1分组的校验
*/
@RequestMapping("/editCommoditySubmit")
public String editCommoditySubmit(Model model,HttpServletRequest request, Integer id,
@Validated(value = {ValidGroup1.class}) CommodityCustom commodityCustom,
BindingResult bindingResult,MultipartFile multipartFile)throws Exception{
//获取校验错误信息
if(bindingResult.hasErrors()){
//输出错误信息
List<ObjectError> allErrors = bindingResult.getAllErrors();
for(ObjectError objectError:allErrors){
//输出错误信息
System.out.println(objectError.getDefaultMessage());
}
//将错误信息传到页面
model.addAttribute("allErrors",allErrors);
return "commodity/editCommodity";
}