《软件开发框架Ⅱ》关键及难点资源-SSM

这是《软件开发框架Ⅱ》课程相关的难点资源文章。
1、spring历史类库下载问题:
springframework版本为:5.0.2,由于当前官网www.spring.io中已经无法直接找到历史版本的二进制版本的库,需要进到repo.spring.io进行下载。
①第一种方法,maven中央仓库根据自己的需要逐个下载库文件:
https://mvnrepository.com/artifact/org.springframework
②第二种方法:进到spring官网的repo库中,https://repo.spring.io/ui/repos/tree
选择Artifacory->snapshot->org->springframework->spring找到对应的版本,这里都是snapshot版本,如本课使用的5.0.2,使用如下包即可。
在这里插入图片描述
其实最终的访问路径是这个:

https://repo.spring.io/artifactory/snapshot/org/springframework/spring/5.0.2.BUILD-SNAPSHOT/spring-framework-5.0.2.BUILD-SNAPSHOT-dist.zip

apo其他组件下载地址:

https://repo1.maven.org/maven2/aopalliance/aopalliance/1.0/aopalliance-1.0.jar
对应maven导入代码:
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
https://repo1.maven.org/maven2/org/aspectj/aspectjweaver/1.8.9/aspectjweaver-1.8.9.jar
aspectjweaver
<dependency>
    <groupId>one.gfw</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.9</version>
</dependency>

commons-logging下载:

https://commons.apache.org/proper/commons-logging/download_logging.cgi

2、工程创建问题:
①idea中,使用Empty Project创建,手工创建src目录;创建lib目录,并将相关的依赖Jar放到其中。
其一,Project Structure设置中,ProjectSettings中,需要调整如下项目:
其二,Project的SDK版本为1.8,Language level为1.8。
其三,Modules中,工程名,将src设置为Sources。
其四,libraries中,添加类库lib的目录。
在这里插入图片描述
将.idea中libraries中的Lib.xml文件中,recursive值改为true
②、beans.xml的问题。
基本内容如下,文件要放到src下(此处可以增加一个resouces,同时在Project Structrue中,将此目录标记为resouce即可),也就是项目的源代码根路径上。:
在这里插入图片描述

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="UserDao" class="com.rainpet.dao.impl.UserDaoImpl">
    </bean>
</beans>

打开beans.xml文件,idea会自动识别spring,点击“Create Spring facet”。
在这里插入图片描述
在这里插入图片描述
勾选对应的beans.xml文件,一步步点确认即可。
③eclipse工程创建问题:
新建一个Java工程,JRE,Use a project specific JRE,选择jdk1.8路径。
点完成。
新的创建工程中,添加一个目录lib。
在Preferences中,Java/Build Path/User Libraries中添加一个lib,在lib上点击,点击Add JARS,将lib文件添加进lib中。

在工程上点右键,属性,在Libraries中,Add Library,选择User libraries,确认退出。
自然有多种方法,可以根据实际情况选择。
src下创建beans.xml,各个需要的包及代码即可。
3、命名空间引入
① aop、ioc、事务、mybatis、SpringMvc试验相关的beans.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:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
    <bean id="user" class="org.rainpet.entity.User">
    </bean>
</beans>

② aop、ioc、事务、mybatis相关试验的Pom.xml的主要依赖引入

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>5.3.39</spring.version>
    </properties>
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>aspectj</groupId>
            <artifactId>aspectj-tools</artifactId>
            <version>1.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.7</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.22.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>

    </dependencies>

③ log4j2的依赖加入:

<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.22.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.22.0</version>
        </dependency>

log4j2的配置文件,文件名:log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <!-- 控制台输出 -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>

        <!-- 文件滚动日志(按日期归档) -->
        <RollingFile name="File" fileName="logs/app.log"
                     filePattern="logs/app-%d{yyyy-MM-dd}.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingFile>
    </Appenders>

    <Loggers>
        <!-- 指定包日志级别  com.rainpet包里面按照如下的配置执行,其他的按照根日志配置执行-->
        <Logger name="com.rainpet" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
<!--            <AppenderRef ref="File"/>-->
        </Logger>

        <!-- 根日志配置 -->
        <Root level="debug">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File"/>
        </Root>
    </Loggers>
</Configuration>

引用示例代码:

LogManager.getLogger().info("Hello World!");

包:

import org.apache.logging.log4j.LogManager;

④ jar包打包相关配置:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.3</version>
                <configuration>
                    <mainClass>org.rainpet.SpringApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

4、事务相关问题
①声明式事务相关beans.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--    <context:component-scan base-package="com.rainpet"/>-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://172.20.94.32:3306/mall"/>
        <property name="username" value="hau"/>
        <property name="password" value="123123"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <tx:advice id="transaction" transaction-manager="transactionManager">
        <!-- 配置事务的传播行为和隔离级别 -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* *Money(..))"/>
        <aop:advisor advice-ref="transaction" pointcut-ref="pointcut"/>
    </aop:config>

    <bean id="accountDao" class="com.rainpet.dao.impl.AccountDaoSpringTxImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
</beans>

业务类的方法,简写:

public class AccountDaoSpringTxImpl implements AccountDao {
    private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
	        this.jdbcTemplate = jdbcTemplate;
	}
    public Double getMoney(String username) {
        Double money=jdbcTemplate.queryForObject("select money from t_account where username=?",Double.class,username);
        System.out.println("get "+username+"'s Money "+money.toString());
        return money;
    }
    @Override
    public boolean subMoney(String username, Double money) {
        PreparedStatement psmt = null;
        int retCount=0;
        retCount=jdbcTemplate.update("update t_account set money=money-? where username=?",money,username);
        System.out.println("subMoney amount "+money.toString()+" successfully");
        if(getMoney(username)<0){
            System.out.println(username+"的余额小于0,扣减失败!");
            throw new RuntimeException("余额不足");
//            return false;
        }
        return true;
    }

    @Override
    public boolean transferMoney(String sourceusername, String desusername, Double money) {
        try{
            boolean addflag= this.addMoney(desusername,money);
//            Integer a=1/0;
            System.out.println("adding amount "+money.toString());
            return subflag&&addflag;
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("transferMoney failed");
            throw e;
//            return false;
        }
    }
  }

②方法二

<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--    <context:component-scan base-package="com.rainpet"/>-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://172.20.94.32:3306/mall"/>
        <property name="username" value="hau"/>
        <property name="password" value="123123"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

<!--    <tx:advice id="transaction" transaction-manager="transactionManager">-->
<!--        &lt;!&ndash; 配置事务的传播行为和隔离级别 &ndash;&gt;-->
<!--        <tx:attributes>-->
<!--            <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED"/>-->
<!--        </tx:attributes>-->
<!--    </tx:advice>-->
<!--    <aop:config>-->
<!--        <aop:pointcut id="pointcut" expression="execution(* *Money(..))"/>-->
<!--        <aop:advisor advice-ref="transaction" pointcut-ref="pointcut"/>-->
<!--    </aop:config>-->

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="accountDao" class="com.rainpet.dao.impl.AccountDaoSpringTxImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
</beans>

此时业务方法就需要加上注解了:

```java
public class AccountDaoSpringTxImpl implements AccountDao {
    private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
	        this.jdbcTemplate = jdbcTemplate;
	}
    public Double getMoney(String username) {
        Double money=jdbcTemplate.queryForObject("select money from t_account where username=?",Double.class,username);
        System.out.println("get "+username+"'s Money "+money.toString());
        return money;
    }
    @Override
    public boolean subMoney(String username, Double money) {
        PreparedStatement psmt = null;
        int retCount=0;
        retCount=jdbcTemplate.update("update t_account set money=money-? where username=?",money,username);
        System.out.println("subMoney amount "+money.toString()+" successfully");
        if(getMoney(username)<0){
            System.out.println(username+"的余额小于0,扣减失败!");
            throw new RuntimeException("余额不足");
//            return false;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean transferMoney(String sourceusername, String desusername, Double money) {
        try{
            boolean addflag= this.addMoney(desusername,money);
//            Integer a=1/0;
            System.out.println("adding amount "+money.toString());
            return subflag&&addflag;
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("transferMoney failed");
            throw e;
//            return false;
        }
    }
  }

5、spring mybatis整合关键文件:
不需要加@Mapper注解,也不用@MapperScan扫包
mybatis-spring.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://mybatis.org/schema/mybatis-spring
        http://mybatis.org/schema/mybatis-spring/mybatis-spring.xsd
">
    <context:component-scan base-package="org.rainpet"/>
    <context:property-placeholder location="db.properties"/>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>
<!--    <bean id="dataSource2" class="org.apache.ibatis.datasource.pooled.PooledDataSource">-->
<!--        <property name="driver" value="${driver}"/>-->
<!--        <property name="url" value="${url}"/>-->
<!--        <property name="username" value="${username}"/>-->
<!--        <property name="password" value="${password}"/>-->
<!--    </bean>-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
<!--    <mybatis-spring:scan base-package="org.rainpet.dao"/>-->
    <import resource="classpath:mybatisConfig.xml"/>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatisConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:org/rainpet/dao/*.xml"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 扫描所有dao接口 -->
        <property name="basePackage" value="org.rainpet.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
</beans>

mybatisConfig.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
        <typeAlias type="org.rainpet.entity.Order" alias="order"/>
    </typeAliases>
    <mappers>
<!--       <mapper resource="dao/OrderMapper2.xml"/>-->
<!--         <package name="org.rainpet.dao"/>-->
    </mappers>
</configuration>

db.properties

db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/mall?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
db.username=root
db.password=123123

Test2Service.java

import org.rainpet.dao.OrderDao2;
import org.rainpet.entity.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class Test2Service {

    @Autowired
    private OrderDao2 orderDao2;

    public void hello() {
        List<Order> orderList= orderDao2.findAll();
        System.out.println(orderList);
    }
}

TestService.java

import org.apache.ibatis.session.SqlSessionFactory;
import org.rainpet.dao.OrderDao2;
import org.rainpet.entity.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class TestService {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public void hello() {
        OrderDao2 orderDao2=sqlSessionFactory.openSession().getMapper(OrderDao2.class);
        List<Order> orderList= orderDao2.findAll();
        System.out.println(orderList);
    }
}

主程序关键代码:

ApplicationContext context=new ClassPathXmlApplicationContext("mybatis-spring.xml");
        Order order=new Order();
        order.setOrderAddress("北京2");
        TestService testService= context.getBean("testService",TestService.class);
        testService.hello();

        Test2Service test2Service= context.getBean("test2Service",Test2Service.class);
        test2Service.hello();

        SqlSessionFactory sqlSessionFactory=context.getBean(SqlSessionFactory.class);
        Integer count=sqlSessionFactory.openSession().getMapper(OrderDao2.class).save(order);
        System.out.println("count:"+count);

6、全注解情况下的mybatis和spring的整合(不是用springboot)
①入口方法的主代码

AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);
Test2Service test2Service= context.getBean("test2Service",Test2Service.class);
        test2Service.hello();

②主配置类:AppConfig.java

import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@ComponentScan("org.rainpet")
@EnableAspectJAutoProxy
@PropertySource("classpath:db.properties")
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

③Mybatis的配置类:MybatisConfig.java

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

@Configuration
@MapperScan("org.rainpet.dao")
public class MybatisConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://172.20.94.32:3306/mall");
        dataSource.setUsername("hau");
        dataSource.setPassword("123123");
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapper/*.xml")); // 替换为您的 Mapper XML 文件路径
        sessionFactory.setTypeAliasesPackage("org.rainpet.entity");
        return sessionFactory.getObject();
    }
}

④启用别名的entity后,会自动的给包中的类别加个首字母小写的别名,也可以再次用@Alias注解指定其他别名:

import org.apache.ibatis.type.Alias;

import java.sql.Date;
import java.time.LocalDateTime;

@Alias("order2")
public class Order {
    private int orderId;
    private LocalDateTime orderTime;
    private String orderAddress;
    private Date orderDate;

    @Override
    public String toString() {
        return "Order{" +
                "orderId=" + orderId +
                ", orderTime=" + orderTime +
                ", orderAddress='" + orderAddress + '\'' +
                ", orderDate=" + orderDate +
                '}';
    }
    public Date getOrderDate() {
        return orderDate;
    }
    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }
    public String getOrderAddress() {
        return orderAddress;
    }
    public void setOrderAddress(String orderAddress) {
        this.orderAddress = orderAddress;
    }
    public int getOrderId() {
        return orderId;
    }
    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }
    public LocalDateTime getOrderTime() {
        return orderTime;
    }
    public void setOrderTime(LocalDateTime orderTime) {
        this.orderTime = orderTime;
    }
}

7、spring、springmvc、mybatis整合,遇到localdatetime类型显示为数组的情况,如下图:
在这里插入图片描述
处理方法:
springmvc-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="org.rainpet"/>
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="objectMapper"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--    <mybatis-spring:scan base-package="org.rainpet.dao"/>-->
<!--    <import resource="classpath:mybatisConfig.xml"/>-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatisConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 扫描所有dao接口 -->
        <property name="basePackage" value="org.rainpet.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

</beans>

还要创建配置类:JacksonConfig.java

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
public class JacksonConfig {
    
    public static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        
        // 配置LocalDateTime序列化格式
        javaTimeModule.addSerializer(LocalDateTime.class, 
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));
            
        objectMapper.registerModule(javaTimeModule);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        
        return objectMapper;
    }
}

主要是此处:

<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="objectMapper"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

同时需要确保pom.xml文件内容:

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.13.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.13.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.datatype</groupId>
      <artifactId>jackson-datatype-jsr310</artifactId>
      <version>2.13.4</version> <!-- 请使用最新版本 -->
    </dependency>

8.数据源的几种常见用法(配置文件中):
①org.springframework.jdbc.datasource.DriverManagerDataSource 无连接池,很少

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
</bean>

②org.apache.commons.dbcp2.BasicDataSource apache的DBCP( Database Connection Pool)的实现,使用的较多

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
    <property name="initialSize" value="5"/>
    <property name="maxTotal" value="10"/>
    <property name="minIdle" value="2"/>
</bean>

③com.zaxxer.hikari.HikariDataSource Hikari数据源,支持连接池,同时也是springboot的默认数据源

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/your_database"/>
        <property name="username" value="your_username"/>
        <property name="password" value="your_password"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="maximumPoolSize" value="10"/>
        <property name="minimumIdle" value="2"/>
        <property name="idleTimeout" value="30000"/>
        <property name="connectionTimeout" value="5000"/>
    </bean>

.yml中:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database
    username: your_username
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2
      idle-timeout: 30000
      connection-timeout: 5000

④com.alibaba.druid.pool.DruidDataSource 阿里巴巴的连接池

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/your_database"/>
        <property name="username" value="your_username"/>
        <property name="password" value="your_password"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="initialSize" value="5"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="2"/>
    </bean>

.yml版本:

spring:
  datasource:
    druid:
      url: jdbc:mysql://localhost:3306/your_database
      username: your_username
      password: your_password
      driver-class-name: com.mysql.cj.jdbc.Driver
      initial-size: 5
      max-active: 10
      min-idle: 2
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin

9、全注解,非spring boot情况下的,SSM的整合,主要使用了servlet的3.0开始的AbstractAnnotationConfigDispatcherServletInitializer支持。

webapp中,WEB-INF中增加一个目录:

services

里面增加一个文件名:

javax.servlet.ServletContainerInitializer

内容为SpringMVC项目的入口配置,WebInit.java,如下:

org.rainpet.config.WebInit

WebInit.java

package org.rainpet.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

/**
 * web工程的初始化,用来代替web.xml
 */
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();;
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
    }
}

WebConfig.java

package org.rainpet.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration    //声明是配置类
@EnableWebMvc     //启动SpringMVC
@ComponentScan("org.rainpet")    //启动组件扫描
public class WebConfig extends WebMvcConfigurerAdapter {
    //配置JSP视图解析器
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
    //配置静态资源处理
    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }
}

SpringConfig.java

package org.rainpet.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

@Configuration
@MapperScan("org.rainpet.mapper")
public class SpringConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mappers/*.xml")); // 指定 Mapper XML 文件所在的位置
        sessionFactory.setTypeAliasesPackage("org.rainpet.entity");
        return sessionFactory.getObject();
    }
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = null;
        try {
            dataSource = new DriverManagerDataSource ();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/rainpet?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC");
            dataSource.setUsername("hau");
            dataSource.setPassword("123123");
//            return dataSource;
        }catch (Exception e){
            e.printStackTrace();
        }
        return dataSource;
    }
}

JacksonConfig.java 用于处理日期格式SR310的日期格式转换:

package org.rainpet.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
public class JacksonConfig {
    
    public static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        
        // 配置LocalDateTime序列化格式
        javaTimeModule.addSerializer(LocalDateTime.class, 
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));
            
        objectMapper.registerModule(javaTimeModule);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        
        return objectMapper;
    }
}

Hibernate验证器的快速失败设置,ValidationConfiguration.java

package org.rainpet.config;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.validation.Validation;

@Configuration
public class ValidationConfiguration {

    public ValidationConfiguration() {
        System.out.println("创建配置类对象:ValidationConfiguration");
    }

    @Bean
    public javax.validation.Validator validator() {
        return Validation.byProvider(HibernateValidator.class)
                .configure() // 开始配置
                .failFast(true) // 配置快速失败
                .buildValidatorFactory() // 构建Validator工厂
                .getValidator(); // 从Validator工厂中获取Validator对象
    }

}

Application.java 入口程序:

package org.rainpet;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;

import java.io.File;

public class Application {

    private static int port = 8080;
    private static String contextPath = "/";

    public static void run(){
        Tomcat tomcat = new Tomcat();
        String baseDir;
        if (Application.class.getResource("/") != null) {
            // 开发调试环境
            baseDir = new File("src/main/webapp").getAbsolutePath();
        } else {
            // 打包运行环境
            baseDir = new File(Application.class.getProtectionDomain().getCodeSource().getLocation().getPath())
                    .getParentFile().getAbsolutePath() + "/webapp";
        }
        //设置tomcat启动后的工作目录
        System.out.println("baseDir:"+baseDir);
        tomcat.setBaseDir(baseDir);
        //设置端口
        tomcat.setPort(port);
        //获取执行器,并设置io协议
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        //设置端口
        connector.setPort(port);
        //设置执行器
        tomcat.setConnector(connector);

        // 修改 context 配置
        Context ctx = tomcat.addWebapp(contextPath, baseDir);
        WebappLoader loader = new WebappLoader(Thread.currentThread().getContextClassLoader());
        ctx.setLoader(loader);

        System.out.println(baseDir);
        tomcat.enableNaming();
        try {
            tomcat.start();
        } catch (LifecycleException e) {
            System.err.println("tomcat 启动失败");
        }
        //tomcat启动后,让其阻塞,不让当前线程结束,等待处理请求,
        tomcat.getServer().await();
    }

    public static void main(String[] args) {
        run();
    }
}

pom.xml的打包部分:

<build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>2.6.13</version>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
            <configuration>
              <classifier>exec</classifier>
              <mainClass>org.rainpet.Application</mainClass>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/webapp</directory>
        <targetPath>META-INF/resources</targetPath>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
    </resources>
  </build>

最后可能会遇到log4j2.xml文件不生效的情况:
需要配置pom.xml
增加依赖:log4j-slf4j2-impl,不然会提示:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j2-impl</artifactId>
      <version>2.20.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.22.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.22.0</version>
    </dependency>

10、常见问题:
① idea 社区版中,p命名空间一直报红,提示错误,但是同样的代码在idea旗舰版中不提示错误。
beans.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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
 ">
    <bean id="user" class="com.rainpet.entity.User" p:userId="1"/>

</beans>

处理方法:
在idea社区版中,设置-语言及框架-Schemas和DTDs中,忽略Schemas和DTDs,添加地址http://www.springframework.org/schema/p,保存即可,代码运行是无问题的。
在这里插入图片描述
②:今天遇到一例问题:
在实验室中试验代码是这个:

@Controller
public class HelloController{

@GetMapping(value = "/hello8",produces = {"application/json;"})
    @ResponseBody
    public Order hello8(){
        Order order=orderMapper.findById(1);
        return order;
    }
}

提示:
No converter for [class org.rainpet.entity.Order] with preset Content-Type ‘null’
检查了依赖:

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.13.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.13.4</version>
    </dependency>

无问题。
检查了用法也无问题。
找了好久才发现,问题在于beans的命名空间,出错的是:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
xmlns:mvc="http://www.springframework.org/schema/tx"

上面这一句错了。应该是:

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

无语了。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwprain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值