SpringMVC+MyBatis+JMS+JTA(分布式事务)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

SpringMVC+MyBatis 相信已经是现在企业开发中常用技术了。
因为一些需求,我们需要集成JMS(我使用的是ActiveMQ),大家应该都知道,MQ也可以认为是一个数据源,数据也是数据源。这种情况下,如果我们在一个方法内操作JMS和数据库,我们就需要保证这个方法执行需要满足原子性。
这也就意味这一个问题,我们要多个数据源在同一个事务中。这里不枚举市面上的所有解决方案,其实atomikos JTA 是一个比较不错分布式事务管理器。
当然如果没有使用到JMS,在需要多数据源(也就是需要连接多个数据库)的情况同样适用。

下面将项目的主要配置贴出来共享:
1、applicationContext.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:amq="http://activemq.apache.org/schema/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core-5.13.0.xsd">

     <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

     <!-- 配置扫描路径 -->
     <context:component-scan base-package="com.hvgroup.zhuhai10086.jms">
        <!-- 只扫描Service,也可以添加Repostory,但是要把Controller排除在外,Controller由spring-mvc.xml去加载 -->
        <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> -->
        <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> -->
        <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
     </context:component-scan>

    <!-- 读取环境变量(自定义扩展)  -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/config.properties</value>
            </list>
        </property>
    </bean>

    <import resource="classpath:spring/applicationContext-Service.xml" />

</beans>  

2、applicationContext-Service.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
    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/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <!-- JDBC连接数据库数据源 -->
    <!-- <bean id="dataSource" -->
    <!-- class="org.springframework.jdbc.datasource.DriverManagerDataSource"> -->
    <!-- <property name="driverClassName" value="${jdbc.driverClassName}" /> -->
    <!-- <property name="url" value="${jdbc.url}" /> -->
    <!-- <property name="username" value="${jdbc.username}" /> -->
    <!-- <property name="password" value="${jdbc.password}" /> -->
    <!-- </bean> -->

    <!-- DBCP连接池 -->
<!--    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" -->
<!--        destroy-method="close"> -->
<!--        <property name="driverClassName" value="${jdbc.driverClassName}" /> -->
<!--        <property name="url" value="${jdbc.url}" /> -->
<!--        <property name="username" value="${jdbc.username}" /> -->
<!--        <property name="password" value="${jdbc.password}" /> -->
<!--        <property name="initialSize" value="20" /> -->
<!--        <property name="maxActive" value="80" /> -->
<!--        <property name="maxIdle" value="100" /> -->
<!--        <property name="minIdle" value="20" /> -->
<!--        <property name="validationQuery" value="SELECT COUNT(*) FROM DUAL"></property> -->
<!--        <property name="testOnBorrow" value="true"></property> -->
<!--        <property name="testOnReturn" value="true"></property> -->
<!--        <property name="testWhileIdle" value="true"></property> -->
<!--    </bean> -->

    <bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
        init-method="init" destroy-method="close">
        <property name="uniqueResourceName" value="ds1" />
<!--        <property name="xaDataSourceClassName" value="${jdbc.driverClassName}" /> -->
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
        <property name="xaProperties">
            <props>
                <prop key="URL">${jdbc.url}</prop>
                <prop key="user">${jdbc.username}</prop>
                <prop key="password">${jdbc.password}</prop>
            </props>
        </property>
<!--        #连接池中保留的最小连接数 -->
        <property name="minPoolSize" value="5" />
<!--        #连接池中保留的最大连接数  -->
        <property name="maxPoolSize" value="20" />
<!--        #最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default:  -->
        <property name="maxIdleTime" value="60" />
        <property name="testQuery">
            <value>select 1</value>
        </property>
    </bean>


    <!-- JNDI连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> -->
    <!-- <property name="jndiName"> -->
    <!-- <value>java:comp/env/jdbc/huiyzl</value> -->
    <!-- </property> -->
    <!-- </bean> -->

    <!-- 配置SqlSessionFactoryBean -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- mapper和resultmap配置路径 -->
        <property name="mapperLocations">
            <list>
                <!-- 注意classpath后面的星号不可省略,否则不能加载jar包中的xml文件 -->
                <value>classpath*:com/hvgroup/zhuhai10086/jms/**/sql/mysql/*Mapper.xml
                </value>
            </list>
        </property>
        <property name="plugins">
            <array>
                <!-- 关于分页插件的使用说明:http://git.oschina.net/free/Mybatis_PageHelper/blob/master/wikis/HowToUse.markdown -->
                <bean class="com.github.pagehelper.PageHelper">
                    <property name="properties">
                        <value>
                            offsetAsPageNum=true
                            rowBoundsWithCount=true
                            reasonable=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

        <!-- 事务管理 --> 
<!--    <bean id="transactionManager" -->
<!--        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> -->
<!--        <property name="dataSource" ref="dataSource" /> -->
<!--    </bean> -->

    <!-- MapperScanner配置,Spring 自动去搜索mapper里的对象,并注入。指定markerInterface表示只有继承SqlMapper接口的接口,才会被扫描映射 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hvgroup.zhuhai10086.jms.**.mapper" />
        <property name="markerInterface" value="com.hvgroup.zhuhai10086.jms.mapper.SqlMapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>


    <bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" 
            init-method="init" destroy-method="shutdownForce">
        <constructor-arg>
            <props>
                <prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
            </props>
        </constructor-arg>
    </bean>

    <bean id="atomikosTransactionManager"  
          class="com.atomikos.icatch.jta.UserTransactionManager"  
          depends-on="userTransactionService"
          init-method="init" destroy-method="close" >  
        <property name="forceShutdown" value="false"/>
    </bean>

    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" >  
        <property name="transactionTimeout" value="300"/>  
    </bean>

    <!-- 分布式事务 -->
    <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
        <property name="transactionManager" ref="atomikosTransactionManager"/>  
        <property name="userTransaction" ref="atomikosUserTransaction"/>  
    </bean>

<!--    <tx:jta-transaction-manager /> -->
    <!-- 可通过注解控制事务,也可以配置拦截器方式配置事务 -->
    <tx:annotation-driven transaction-manager="jtaTransactionManager" />

</beans>

3、ActiveMQ-XA.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:amq="http://activemq.apache.org/schema/core"
    xmlns:jms="http://www.springframework.org/schema/jms"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/jms
        http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core-5.13.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <!-- 重发策略:最多重发次数=maximumRedeliveries -->
    <amq:redeliveryPolicy id="redeliveryPolicy"
        maximumRedeliveries="6" />

    <!-- 抓取策略 -->
    <amq:prefetchPolicy id="prefetchPolicy" queuePrefetch="5" topicPrefetch="5" />

    <!-- activeMQ连接信息,XA事务 -->
    <amq:xaConnectionFactory id="jmsXaConnectionFactory"
        brokerURL="${activemq.brokerURL}" 
        userName="${activemq.username}" 
        password="${activemq.password}"
        redeliveryPolicy="#redeliveryPolicy"
        alwaysSessionAsync="false"
        alwaysSyncSend="true" 
        prefetchPolicy="#prefetchPolicy"/>



    <bean id="amqConnectionFactory"  
          class="com.atomikos.jms.AtomikosConnectionFactoryBean" init-method="init" destroy-method="close">  
        <property name="uniqueResourceName" value="XAactiveMQ"/>  
        <property name="xaConnectionFactory" ref="jmsXaConnectionFactory"/>  
        <property name="poolSize" value="100"/>
    </bean>

    <!-- ====Producer side start==== -->

    <!-- 定义JmsTemplate的Queue类型 -->
    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="amqConnectionFactory" />
        <!-- 非pub/sub模型(发布/订阅),即队列模式 -->
        <property name="pubSubDomain" value="false" />
    </bean>

    <!-- 定义JmsTemplate的Topic类型 -->
    <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="amqConnectionFactory" />
        <!-- pub/sub模型(发布/订阅) --> 
        <property name="pubSubDomain" value="true" />
    </bean>

    <!-- ====Producer side end==== -->

    <!-- ====Consumer side start==== -->

    <!--这个是sessionAwareQueue目的地(响应消息)-->  
    <amq:queue id="queueReceiver2ResponseDestination"  physicalName="test.queue2.response" />

    <!-- 定义Queue监听器(无事务) -->
    <jms:listener-container
        destination-type="queue" 
        container-type="default" 
        connection-factory="amqConnectionFactory" 
        error-handler="jmsErrorHandler"
        acknowledge="auto">
        <jms:listener destination="xinge.queue.push" ref="xgMessageReceiver"  concurrency="5-100" />
        <jms:listener destination="xinge.queue.push.device.multiple" ref="xgMessageReceiverMultiple"  concurrency="5-100" />
    </jms:listener-container>

    <!-- 定义Queue监听器(有事务) -->
    <jms:listener-container
        destination-type="queue" 
        container-type="default" 
        connection-factory="amqConnectionFactory" 
        transaction-manager="jtaTransactionManager"
        error-handler="jmsErrorHandler"
        acknowledge="transacted">
        <jms:listener destination="xinge.queue.push.invokelog" ref="xgMessageReceiverInvokeLog"  concurrency="5-100" />
<!--        <jms:listener destination="test.queue" ref="queueReceiver"  concurrency="10-100" /> -->
<!--        <jms:listener destination="test.queue2" ref="queueReceiver2"  concurrency="2-10"/> -->
<!--        <jms:listener destination="test.queue2.response" ref="queueReceiver2Response" concurrency="2-10" /> -->
    </jms:listener-container>

    <!-- 定义Topic监听器 -->
<!--    <jms:listener-container  -->
<!--        destination-type="topic"   -->
<!--        container-type="default"  -->
<!--        connection-factory="amqConnectionFactory" -->
<!--        transaction-manager="jtaTransactionManager" -->
<!--        error-handler="jmsErrorHandler" -->
<!--        acknowledge="transacted" > -->
<!--        <jms:listener destination="test.topic" ref="topicReceiver" /> -->
<!--        <jms:listener destination="test.topic" ref="topicReceiver2" /> -->
<!--    </jms:listener-container> -->

    <!-- ====Consumer side end==== -->

    <bean id="xingeApp" class="com.tencent.xinge.XingeApp">
        <constructor-arg index="0" value="2100170086"/><!-- accessId -->
        <constructor-arg index="1" value="2d257b10220bc3849743ffe0e9bd233a"/><!-- secretKey -->
    </bean>

</beans>  

4、spring-mvc.xml

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

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

    <!-- 静态资源文件,不会被Spring MVC拦截 -->
    <mvc:resources location="/resources/" mapping="/resources/**"/>

    <!-- 指定Sping组件扫描的基本包路径 -->
    <context:component-scan base-package="com.hvgroup.zhuhai10086.jms" >
        <!-- 这里只扫描Controller,不可重复加载Service -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- JSP视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="prefix" value="/WEB-INF/views/" />  
        <property name="suffix" value=".jsp" />
        <property name="order" value="1" />
    </bean>

</beans>  

5、config.properties

jdbc.url=jdbc:mysql://localhost:3306/xgmessage?useUnicode=true&amp;characterEncoding=utf-8&amp;relaxAutoCommit=true
jdbc.username=root
jdbc.password=123456

activemq.brokerURL=tcp://localhost:61616
activemq.username=admin
activemq.password=admin

6、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:web="http://java.sun.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>zhuhai10086-jms</display-name>
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>zhuhai10086-jms</param-value>
    </context-param>
    <!-- Log4j配置 -->
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j/log4j.xml</param-value>
    </context-param>
    <!-- 加载log4j配置文件 -->
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <filter>
        <filter-name>characterEncoding</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/applicationContext.xml,classpath*:activemq/ActiveMQ-XA.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <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>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

7、把log4j.xml 也贴出来吧,兴许有的同学能用上

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd">
<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d][%p][%13F:%L] %m%n" />
        </layout>
    </appender>
    <appender name="DEBUG" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="${log4j.logfile.path}" />
        <param name="Encoding" value="UTF-8" />
        <param name="DatePattern" value="'.'yyyy-MM-dd" />
        <param name="ImmediateFlush" value="true" />
        <param name="Append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d][%p] %m%n" />
        </layout>
    </appender>

    <logger name="java.sql.Connection">
        <level value="DEBUG" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="java.sql.PreparedStatement">
        <level value="DEBUG" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="java.sql.Statement">
        <level value="DEBUG" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="java.sql.ResultSet">
        <level value="DEBUG" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="org.mybatis">
        <level value="DEBUG" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="org.springframework">
        <level value="INFO" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>   
    <logger name="org.apache.ibatis">
        <level value="INFO" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="org.apache.xbean.spring">
        <level value="INFO" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="com.atomikos">
        <level value="ERROR" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="org.apache.activemq">
        <level value="INFO" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>

    <logger name="com.hvgroup">
        <level value="DEBUG"/>
        <appender-ref ref="DEBUG" />
        <appender-ref ref="CONSOLE" />
    </logger>

    <!-- Root Logger -->
    <root>
        <level value="DEBUG"/>
    </root>

</log4j:configuration>

对需要使用数据库数据源的方法使用 @Transactional 注解即可,在配置上,JMS的事务我们已经在配置文件中指定了。如下代码中指定的 transaction-manager=”jtaTransactionManager”:

    <!-- 定义Queue监听器(有事务) -->
    <jms:listener-container
        destination-type="queue" 
        container-type="default" 
        connection-factory="amqConnectionFactory" 
        transaction-manager="jtaTransactionManager"
        error-handler="jmsErrorHandler"
        acknowledge="transacted">
        <jms:listener destination="xinge.queue.push.invokelog" ref="xgMessageReceiverInvokeLog"  concurrency="5-100" />
    </jms:listener-container>

最后贴上工程代码的结构图:
工程结构图

声明:本文是我在项目实际业务开发之前搭建的框架,其中如出现一些敏感字,声明不涉及版权问题。
贴出的配置,仅供大家学习。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
13天前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
24 4
|
1月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
123 2
|
2月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
65 2
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
212 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
3月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
4月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
4月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
4月前
|
前端开发 应用服务中间件 数据库
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
这篇文章通过一个具体的项目案例,详细讲解了如何使用SpringMVC、Thymeleaf、Bootstrap以及RESTful风格接口来实现员工信息的增删改查功能。文章提供了项目结构、配置文件、控制器、数据访问对象、实体类和前端页面的完整源码,并展示了实现效果的截图。项目的目的是锻炼使用RESTful风格的接口开发,虽然数据是假数据并未连接数据库,但提供了一个很好的实践机会。文章最后强调了这一章节主要是为了练习RESTful,其他方面暂不考虑。
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查