SSM框架整合:完成登录,解释配置文件为何这么使用,父子容器问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41376740/article/details/82914973

前言

  简单学习了SSM框架,现在开始完成第一个任务:SSM框架整合,以及搞明白为什么要这么配置文件~第一次整合,搞明白里面如何运作是很关键的。

项目目录

在这里插入图片描述

名称 作用
mapper mybatis映射文件
spring spring家族配置文件=context为父(全局性)+mybatis整合+transaction事务+mvc
jdbc-druid-config druid配置文件
log4j2 log文件
mybatis-config mybatis的配置文件

项目依赖

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.0.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.12</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.11.1</version>
        </dependency>

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

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.11</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
    </dependencies>

依赖没进行整理,有的用不到是尝试用的,可以根据需要进行删减。

配置文件

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--告诉它spring配置文件在哪-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/spring-context.xml</param-value>
    </context-param>

    <!--这个比较关键:通过Listener来加载IOC容器上下文,就是一个桥梁-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--编码过滤器-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--分发任务Servlet-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--制定mvc配置文件在哪-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--这里是'/'而不是'/*'-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

理解一哈:

  • Listener: 这里的Listener是比较意思的地方,当tomcat加载完servletContext上下文之后,它怎么知道要加载spring的呢?还记得Listener监听器的作用,这里可以认为是servletContext起来了之后,监听器监听到了,就开始启动spring加载IOC容器了。知道它的作用就可以了。
  • dispatcherServlet: 是一个管家。它就像快递的中转站一样,来了一个请求,我就把它送给某一个Servlet去处理。

druid 数据库连接池

# database configure
jdbc.url                                        = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=true&rewriteBatchedStatements=true
jdbc.username                                   = root
jdbc.password                                   = lyy1314520

# druid datasource
druid.initialSize                               = 10
druid.minIdle                                   = 10
druid.maxActive                                 = 50
druid.maxWait                                   = 60000
druid.timeBetweenEvictionRunsMillis             = 60000
druid.minEvictableIdleTimeMillis                = 300000
druid.validationQuery                           = SELECT 1
druid.testWhileIdle                             = true
druid.testOnBorrow                              = false
druid.testOnReturn                              = false
druid.poolPreparedStatements                    = false
druid.maxPoolPreparedStatementPerConnectionSize = 20

log4j2

status = error
name = PropertiesConfig

filters = threshold

filter.threshold.type = ThresholdFilter
filter.threshold.level = debug

appenders = console

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT

重点!spring配置文件整合

老大哥:全局context文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="dao"/>
    <context:component-scan base-package="service"/>

    <import resource="spring-context-mybatis.xml"/>
    <import resource="spring-context-transaction.xml"/>
</beans>

完成了2个任务,一个扫描dao,一个扫描service,然后就是导入另外两个配置文件,这样的作用是,让整个配置条理很清晰,不要把它们挤在一起。


二哥:mybatis 整合

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

    <!--配置properties文件的位置-->
    <context:property-placeholder location="classpath:jdbc-druid-config.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!-- 基本属性 url、user、password -->
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${druid.initialSize}"/>
        <property name="minIdle" value="${druid.minIdle}"/>
        <property name="maxActive" value="${druid.maxActive}"/>

        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${druid.maxWait}"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}"/>

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}"/>

        <property name="validationQuery" value="${druid.validationQuery}"/>
        <property name="testWhileIdle" value="${druid.testWhileIdle}"/>
        <property name="testOnBorrow" value="${druid.testOnBorrow}"/>
        <property name="testOnReturn" value="${druid.testOnReturn}"/>

        <!-- 打开PSCache,并且指定每个连接上PSCache的大小  如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。-->
        <property name="poolPreparedStatements" value="${druid.poolPreparedStatements}"/>
        <property name="maxPoolPreparedStatementPerConnectionSize"
                  value="${druid.maxPoolPreparedStatementPerConnectionSize}"/>

        <!--End 慢sql监控及log4j设置,不想监控的话将proxyFilters属性删除即可 -->

    </bean>
    <!--配置sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!--配置mapper扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="dao"/>
    </bean>
</beans>

这个没啥好说的,就是这么配置咯~然后properties配置字面量,引用等


三哥:事务处理

<?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"
       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">

    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

三哥也简单


儿子:mvc

<?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: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">

    <!-- 配置jsp显示ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--开启mvc注解-->
    <mvc:annotation-driven/>

    <!--让它只扫描Controller-->,其实这里不需要添加filter的因为我们只是在controller中扫描
    <context:component-scan base-package="controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>

为什么要这么配?->父子容器问题

理论
  有没有发现一个巨大的问题:为什么要把controller单独拉出来,单独进行扫描呢?一次性扫描完了,不就完事了?还这么费劲?这里一个比较重要的概念:父子容器,父亲(Spring) 儿子(mvc)。
  在spring和spring-mvc中,分别是父容器和子容器,父容器不能访问子容器的bean,子容器可以访问父容器的bean,想一下,如果spring上来就把所有的bean 都装到自己的bean里面了。默认情况下,SpringMVC会在自己的容器里面找Controller,于是它找呀找呀,发现就是没有,那不得急死了,Controller啊你在哪里,mmp被Spring抢走了,于是gg了。于是我就想到了一个问题。还记得我们写代码的时候在Controller里面装配Service,这似乎就是子容器访问父容器。水到渠成~
操作

  • 第一种就是我们固定包扫描不全局扫描
  • 第二种,我已经启用了全局扫描,这个时候可以通过include-filter和exclude-filter进行包含和剔除,就像儿子mvc中写的那样也能完成~

配置到此结束~来个例子练练手:完成登录

实现登录

Controller

@Controller
@SessionAttributes(value = {"message"})
public class UserController {

    @Autowired
    private UserService userService;

    @Transactional
    @RequestMapping("/login")
    public String login(User2 user2, Model model) {
        User2 user = userService.loginUser(user2);
        if (user != null) {
            model.addAttribute("message", "登录成功");
            return "success";
        }
        return null;
    }
}

Service

public interface UserService {

    User2 loginUser(User2 user2);
}

@Service
public class UserServiceImpl implements service.UserService {

    @Autowired
    private UserDao dao;

    @Override
    public User2 loginUser(User2 user2) {
        return dao.login(user2);
    }

}

dao

public interface UserDao {

    User2 login(User2 user);
}

mapper

<mapper namespace="dao.UserDao">
    <select id="login" resultType="bean.User2">
        select *
        from user
        where username = #{username} and password = #{password}
    </select>
</mapper>

这样简单的配置就完成了。

可能遇到的问题

1、bean找不到,Service等。
主要原因:

  • 配置文件是否配置正确,尤其是在web.xml里面,这里面定义的是配置文件的位置。扫描不到有一定程度因为它。比如,你只是指定了Context的位置,却没有import其它。可以用-*.xml指定全部位置。
  • 注解是否加对

2、某个类找不到,依赖没弄好
3、…忘记了,出了问题可以留言,或者google把~

总结

此次最大的莫过于,父子容器问题。知道了为什么两个扫描要分开的原因在哪。加上配置文件的一些细节部分,收获挺大。

猜你喜欢

转载自blog.csdn.net/qq_41376740/article/details/82914973
今日推荐