Spring之路(34)–使用xml配置Spring+SpringMVC+MyBatis(SSM)项目完整实例

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 本文目录0. 概述1. 新建项目2. 导入jar包3. 配置web.xml4. 配置spring-config.xml5. 配置mybatis-config.xml6. 编写映射文件7. 开发各层逻辑代码8. 总结

0. 概述

本篇介绍下如何使用xml配置SSM项目(如果要表达的更加严谨,其实除了xml配置,还有注解配置),并实现对单表(还是之前一直举例的blog表)增删改查操作。


因为需要配置的东西比较多,所以还是要简单的说下思路,先理顺了整体思路,才容易理解每个局部是在干什么。


首先需要新建一个网站项目,然后引入相关的jar包,因为SSM框架是别人封装好的,所以需要引入别人的jar。

因为是网站项目,所以需要配置web.xml,这个配置文件是网站项目配置文件。当网站启动时,会加载其中的配置。

需要配置spring-config.xml,我需要对spring容器进行配置,包括控制器组件、服务组件、数据库操作、数据源组件、MyBatis组件,都需要容器进行管理,spring配置是整个项目的核心配置。从此处可以看出MyBatis是通过spring集成进来的,在Spring一切皆组件的思想下,集成一个第三方框架是一个很简单事情。

配置mybatis-config.xml,此处是对mybatis进行配置,mybatis组件在进入容器管理时,携带该配置信息进入。spring负责管理mybatis组件,mybatis组件初始化时需要的配置信息就在mybatis-config.xml。

依次开发数据库操作层、服务层、控制器层,前端视图页面,然后进行操作验证。

通过项目结构图了解下整体项目结构跟构建顺序:

image.png

1. 新建项目

File-New-Other Project-Dynamic Web Project,建立一个动态网站项目,项目名称xmlssmdemo


2. 导入jar包

除了spring相关的jar包(已经指示过多次不再具体指示),还需要导入下面的jar包:


commons-logging-1.2.jar 日志相关

jackson-annotations-2.8.0.jar json相关

jackson-core-2.8.0.jar json相关

jackson-databind-2.8.0.jar json相关

mysql-connector-java-5.1.48.jar mysql驱动

druid-1.1.21.jar 数据库连接池

mybatis-3.5.3.jar mybatis相关

mybatis-spring-2.0.3.jar mybatis-spring相关

3. 配置web.xml

当我们的网站项目启动时,会加载web.xml配置,此时我们要配置下DispatcherServlet及其匹配的映射路径,同时引入spring容器的配置文件spring-config.xml,具体如下:


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

id="WebApp_ID" version="3.1">

<display-name>xmlssmdemo</display-name>

<servlet>

 <servlet-name>springmvc</servlet-name>

 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

 <init-param>

  <param-name>contextConfigLocation</param-name>

  <!-- 引入spring-config.xml配置文件,该文件用来配置spring容器 -->

  <param-value>/WEB-INF/spring-config.xml</param-value>

 </init-param>

 <load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

 <servlet-name>springmvc</servlet-name>

 <!-- 配置DispatcherServlet对应所有请求(*表示所有) -->

 <url-pattern>/*</url-pattern>

</servlet-mapping>

</web-app>


4. 配置spring-config.xml

很多开发者喜欢将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:context="http://www.springframework.org/schema/context"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xsi:schemaLocation="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">

<!-- 第一步,配置MyBatis用来操作数据,sqlSessionFactory就是MyBatis中用来操作数据库的 -->

<bean id="sqlSessionFactory"

 class="org.mybatis.spring.SqlSessionFactoryBean">

 <property name="dataSource" ref="dataSource" />

 <!-- 引入Mybatis的配置文件,MyBatis组件需要它 -->

 <property name="configLocation"

  value="classpath:org/maoge/xmlssmdemo/config/mybatis-config.xml" />

</bean>

<!-- 第二步,配置数据源,可以看到sqlSessionFactory需要注入该数据源 -->

<bean id="dataSource"

 class="com.alibaba.druid.pool.DruidDataSource">

 <property name="driverClassName"

  value="com.mysql.jdbc.Driver"></property>

 <property name="url"

  value="jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&amp;characterEncoding=utf-8"></property>

 <property name="username" value="root"></property>

 <property name="password" value="Easy@0122"></property>

</bean>

<!-- 第三步,将org.maoge.xmlssmdemo.dao包下的类注册为bean,注意此处是注册为MyBatis方式管理的可操作数据库的bean -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

 <property name="sqlSessionFactoryBeanName"

  value="sqlSessionFactory" />

 <property name="basePackage" value="org.maoge.xmlssmdemo.dao" />

</bean>

<!-- 第四步,扫描控制器层和服务层 -->

<context:component-scan

 base-package="org.maoge.xmlssmdemo.controller" />

<context:component-scan

 base-package="org.maoge.xmlssmdemo.service" />

<!--第五步,开启通过注解配置访问路径与方法的匹配 -->

<mvc:annotation-driven />

<!--第六步,配置静态资源映射 -->

<mvc:resources mapping="/static/**" location="/static/" />

</beans>


简单的总结下,就是引入MyBaits组件,然后MyBatis是访问数据库的操作组件,还需要数据源,所以配置上数据源组件。在配置MyBatis组件时,还需要指定MyBatis组件的配置文件。


然后就是要扫描控制器层、服务层、数据库操作层,其中数据库操作层因为使用了MyBatis,所以需要使用一个定义好的MapperScannerConfigurer类型的bean来扫描该层。


最后就是常用配置了,开了注解驱动,然后配置了对静态资源访问的映射。


5. 配置mybatis-config.xml

在配置spring.xml时,有如下一行代码:


  <bean id="sqlSessionFactory"

   class="org.mybatis.spring.SqlSessionFactoryBean">

   <property name="dataSource" ref="dataSource" />

   <!-- 引入Mybatis的配置文件,MyBatis组件需要它 -->

   <property name="configLocation"

    value="classpath:org/maoge/xmlssmdemo/config/mybatis-config.xml" />


可以看出,Spring容器中有sqlSessionFactory这个bean组件,而该组件有个参数是mybatis-config.xml,也就是说Spring容器在注册sqlSessionFactory时,会加载mybatis-config.xml文件信息。


该xml文件制定了ORM元数据文件的位置,ORM元数据文件就是保存数据库表与Java对象之间映射关系的。mybatis-config.xml代码如下:


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<mappers><!-- 映射器告诉MyBatis到哪里去找映射文件 -->

 <mapper resource="org/maoge/xmlssmdemo/config/BlogMapper.xml" />

</mappers>

</configuration>


6. 编写映射文件

再捋下子加载流程哈,别懵了。web项目启动–加载web.xml–加载配置的spring.xml–加载MyBatis的sqlSessionFactory组件–加载MyBatis配置文件mybatis-config.xml读取其中的映射信息。


所谓的映射,这个就是告诉我们的程序,数据库中的表blog对应Java类BlogDo,然后也得将表中的列与BlogDo中的属性对应关系描述出来。这样如果是由10行数据的表格,就对应size为10的List<BlogDo>,这个必须得理解啊,如果这个理解不了,那…,还是先补补基础知识吧。


OK,下面我们来具体看下到底是怎么映射的哈,BlogMapper.xml如下:


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.maoge.xmlssmdemo.dao.BlogDao">

<select id="getById" parameterType="Long"

 resultType="org.maoge.xmlssmdemo.xdo.BlogDo">

 select * from blog where id = #{id}

</select>

</mapper>


首先下面这部分,是固定的头部,不用去管。


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


然后,看下面部分,namespace的值跟BlogDao类有一个对应,也就是说当执行BlogDao类中的方法时,会从该配置文件中找对应的配置来执行。


<mapper namespace="org.maoge.xmlssmdemo.dao.BlogDao">

1

然后,下面部分表示,当执行BlogDao类中的getById方法时,会转成下面对应的sql语句来执行,即执行select * from blog where id = #{id},同时#{id}是一个占位符号,根据parameterType="Long",会把BlogDao类中的getById方法的Long类型的参数,注入到select * from blog where id = #{id}的#{id}的位置,也就是说如果执行getById(101),则会转换成执行sqlselect * from blog where id = 101。

执行结果根据resultType="org.maoge.xmlssmdemo.xdo.BlogDo",也就是说列名会自动对应到BlogDo同名的属性中。


<select id="getById" parameterType="Long"

 resultType="org.maoge.xmlssmdemo.xdo.BlogDo">

 select * from blog where id = #{id}

</select>


所以通过映射文件,程序真正知道了当执行数据操作层(Dao)层方法时,该如何转换为执行的sql语句,又该如何将结果返回为Java对象。


7. 开发各层逻辑代码

剩下的工作就都是类似的了,无非就是记忆下增删改查具体在BlogMapper.xml文件中的写法,此处我们贴下代码:


修改BlogMapper.xml代码


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.maoge.xmlssmdemo.dao.BlogDao">

<!-- 获取一个 -->

<select id="getById" parameterType="Long"

 resultType="org.maoge.xmlssmdemo.xdo.BlogDo">

 select * from blog where id = #{id}

</select>

<!-- 获取列表 -->

<select id="getList"

 resultType="org.maoge.xmlssmdemo.xdo.BlogDo">

 select * from blog

</select>

<!-- 插入 -->

<insert id="insert"

 parameterType="org.maoge.xmlssmdemo.xdo.BlogDo">

 insert into

 blog(author,content,title)values(#{author},#{content},#{title})

</insert>

<!-- 更新 -->

<update id="update"

 parameterType="org.maoge.xmlssmdemo.xdo.BlogDo">

 update blog set

 author=#{author},content=#{content},title=#{title} where

 id=#{id}

</update>

<!-- 删除 -->

<delete id="delete" parameterType="Long">

 delete from blog where

 id=#{id}

</delete>

</mapper>


然后BlogDao里面的方法名字与BlogMapper.xml中的id一一对应:


package org.maoge.xmlssmdemo.dao;


import java.util.List;


import org.maoge.xmlssmdemo.xdo.BlogDo;

import org.springframework.stereotype.Repository;


@Repository

public interface BlogDao {

  BlogDo getById(Long id);


  List<BlogDo> getList();


  int insert(BlogDo blog);


  int update(BlogDo blog);


  int delete(Long id);

}


剩下的数据对象BlogDo、服务类BlogService、控制类BlogController与视图页面blog.html与之前一模一样了,直接贴代码:


package org.maoge.xmlssmdemo.xdo;

/**

* @theme 数据对象--博客

* @author maoge

* @date 2020-01-29

*/

public class BlogDo {

  private Long id;

  private String title;

  private String author;

  private String content;

  // 省略get get

}


package org.maoge.xmlssmdemo.service;


import java.util.List;


import org.maoge.xmlssmdemo.dao.BlogDao;

import org.maoge.xmlssmdemo.xdo.BlogDo;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;


@Service

public class BlogService {

@Autowired

private BlogDao blogDao;


/**

 * 获取博客列表

 */

public List<BlogDo> getBlogList() {

 return blogDao.getList();

}


/**

 * 按id获取博客信息

 */

public BlogDo getBlogById(Long id) {

 return blogDao.getById(id);

}


/**

 * 新增博客

 */

public void addBlog(BlogDo blog) {

 blogDao.insert(blog);

}


/**

 * 根据博客id更新博客信息

 */

public void updateBlog(BlogDo blog) {

 blogDao.update(blog);

}


/**

 * 根据博客id删除对应博客

 */

public void deleteBlog(Long id) {

 blogDao.delete(id);

}

}


package org.maoge.xmlssmdemo.controller;


import java.util.List;


import org.maoge.xmlssmdemo.service.BlogService;

import org.maoge.xmlssmdemo.xdo.BlogDo;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.DeleteMapping;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.PutMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;


/**

* @theme 控制器--博客

* @author maoge

* @date 2020-01-28

*/

@RestController // 通过该注解,第一将BlogController注册为控制器,第二将其中方法返回值转换为json

public class BlogController {

@Autowired // 自动装配blogService

private BlogService blogService;


/**

 * 查询博客信息 1、@GetMapping表示可以使用get方法请求该api

 * 2、"/blog/{id}"表示请求路径为/blog/{id}的形式,其中{id}为占位符

 * 3、@PathVariable("id")表示将占位符{id}的值传递给id 4、也就是说/blog/123请求的话,会将123传递给参数id

 */

@GetMapping(value = "/blog/{id}")

public BlogDo getOne(@PathVariable("id") long id) {

 return blogService.getBlogById(id);

}


/**

 * 查询博客列表,使用get方法

 */

@GetMapping("/blog")

public List<BlogDo> getList() {

 return blogService.getBlogList();

}


/**

 * 新增博客 1、@PostMapping表示使用post方法

 * 2、@RequestBody表示将请求中的json信息转换为BlogDo类型的对象信息,该转换也是由SpringMVC自动完成的

 */

@PostMapping("/blog")

public void add(@RequestBody BlogDo blog) {

 blogService.addBlog(blog);

}


/**

 * 修改博客 实际上此处也可以不在路径中传递id,而是整个使用json传递对象信息,但是我查询了一些文档,貌似使用路径传递id更加规范一些,此处不用纠结

 */

@PutMapping("/blog/{id}")

public void update(@PathVariable("id") long id, @RequestBody BlogDo blog) {

 // 修改指定id的博客信息

 blog.setId(id);

 blogService.updateBlog(blog);

}


/**

 * 删除博客

 */

@DeleteMapping("/blog/{id}")

public void delete(@PathVariable("id") long id) {

 blogService.deleteBlog(id);

}

}


<!DOCTYPE html>

<html>


<head>

<meta charset="UTF-8">

<title></title>

<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->

<link rel="stylesheet"

href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"

integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"

crossorigin="anonymous">

</head>


<body>

<nav class="navbar navbar-inverse">

 <div class="container-fluid">

  <ul class="nav navbar-nav">

   <li><a href="#" onclick="viewBlogs()">浏览博客</a></li>

   <li><a href="#" onclick="addBlog()">新增博客</a></li>

  </ul>

 </div>

</nav>

<table id="blogTable" class="table table-striped">

 <tr>

  <th>ID</th>

  <th>标题</th>

  <th>作者</th>

  <th>操作</th>

 </tr>

</table>

<!-- 新增弹窗 -->

<div id="blogAddModal" class="modal fade" tabindex="-1" role="dialog">

 <div class="modal-dialog" role="document">

  <div class="modal-content">

   <div class="modal-header">

    <h4 class="modal-title">新增博客</h4>

   </div>

   <div class="modal-body" style="padding: 16px;">

    <!-- 新增博客的表单 -->

    <form>

     <div class="form-group">

      <label>标题</label> <input name="title" type="text"

       class="form-control">

     </div>

     <div class="form-group">

      <label>内容</label>

      <textarea name="content" class="form-control" rows="3"></textarea>

     </div>

     <div class="form-group">

      <label>作者</label> <input name="author" type="text"

       class="form-control">

     </div>

    </form>

   </div>

   <div class="modal-footer">

    <button type="button" class="btn btn-primary"

     onclick="addBlogSubmit()">提交</button>

    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>

   </div>

  </div>

 </div>

</div>

<!-- 编辑弹窗 -->

<div id="blogEditModal" class="modal fade" tabindex="-1" role="dialog">

 <div class="modal-dialog" role="document">

  <div class="modal-content">

   <div class="modal-header">

    <h4 class="modal-title">编辑博客</h4>

   </div>

   <div class="modal-body" style="padding: 16px;">

    <!-- 编辑博客的表单 -->

    <form>

     <div class="form-group">

      <label>ID</label> <input name="id" type="text"

       class="form-control" readonly>

     </div>

     <div class="form-group">

      <label>标题</label> <input name="title" type="text"

       class="form-control">

     </div>

     <div class="form-group">

      <label>内容</label>

      <textarea name="content" class="form-control" rows="3"></textarea>

     </div>

     <div class="form-group">

      <label>作者</label> <input name="author" type="text"

       class="form-control">

     </div>

    </form>

   </div>

   <div class="modal-footer">

    <button type="button" class="btn btn-primary"

     onclick="editBlogSubmit()">提交</button>

    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>

   </div>

  </div>

 </div>

</div>

</body>

<!--jQuery-->

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->

<script

src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"

integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"

crossorigin="anonymous">


</script>

<script>

//浏览博客

function viewBlogs() {

 var row = "";

 //先清空表格

 $('#blogTable').find("tr:gt(0)").remove();

 $

   .ajax({

    type : "GET",

    url : "/xmlssmdemo/blog",

    dataType : "json",

    contentType : "application/json; charset=utf-8",

    success : function(res) {

     $

       .each(

         res,

         function(i, v) {

          row = "<tr>";

          row += "<td>" + v.id + "</td>";

          row += "<td>" + v.title + "</td>";

          row += "<td>" + v.author + "</td>";

          row += "<td><a class='btn btn-primary btn-sm' href='#' οnclick='editBlog("

            + v.id + ")'>编辑</a>";

          row += "<a class='btn btn-danger btn-sm' href='#' οnclick='deleteBlog("

            + v.id + ")'>删除</a></td>";

          row += "</tr>";

          $("#blogTable").append(row);

         });

    },

    error : function(err) {

     console.log(err);

    }

   });

}

//新增

function addBlog() {

 $('#blogAddModal').modal('show');

}

//新增提交

function addBlogSubmit() {

 var data = {

  id : '',

  title : $("#blogAddModal input[name='title']").val(),

  author : $("#blogAddModal input[name='author']").val(),

  content : $("#blogAddModal textarea[name='content']").val()

 };

 $.ajax({

  type : "POST",

  url : "/xmlssmdemo/blog",

  //dataType: "json",

  contentType : "application/json; charset=utf-8",

  data : JSON.stringify(data), //需要将对象转换为字符串提交

  success : function() {

   //新增后重新加载

   viewBlogs();

   //关闭弹窗

   $('#blogAddModal').modal('hide');

  },

  error : function(err) {

   console.log(err);

  }

 });

}

//编辑

function editBlog(id) {

 //查询博客信息

 $.ajax({

  type : "GET",

  url : "/xmlssmdemo/blog/" + id,

  dataType : "json",

  contentType : "application/json; charset=utf-8",

  success : function(res) {

   console.log(res);

   //为编辑框赋值

   $("#blogEditModal input[name='id']").val(res.id);

   $("#blogEditModal input[name='title']").val(res.title);

   $("#blogEditModal input[name='author']").val(res.author);

   $("#blogEditModal textarea[name='content']").val(res.content);

   //显示编辑弹窗

   $('#blogEditModal').modal('show');

  },

  error : function(err) {

   console.log(err);

  }

 });

}

//编辑提交

function editBlogSubmit() {

 var data = {

  id : $("#blogEditModal input[name='id']").val(),

  title : $("#blogEditModal input[name='title']").val(),

  author : $("#blogEditModal input[name='author']").val(),

  content : $("#blogEditModal textarea[name='content']").val()

 };

 $.ajax({

  type : "PUT",

  url : "/xmlssmdemo/blog/" + data.id,

  //dataType: "json",

  contentType : "application/json; charset=utf-8",

  data : JSON.stringify(data), //需要将对象转换为字符串提交

  success : function() {

   //新增后重新加载

   viewBlogs();

   //关闭弹窗

   $('#blogEditModal').modal('hide');

  },

  error : function(err) {

   console.log(err);

  }

 });

}

//删除

function deleteBlog(id) {

 $.ajax({

  type : "DELETE",

  url : "/xmlssmdemo/blog/" + id,

  //dataType: "json",//由于删除方法无返回值,所以此处注释掉

  contentType : "application/json; charset=utf-8",

  success : function() {

   //删除后重新加载

   viewBlogs();

  },

  error : function(err) {

   console.log(err);

  }

 });

}

</script>


</html>


8. 总结

看明白了,基于Spring组件思想之后,我们只是把使用SpringJDBC实现的BlogDao替换为了使用MyBatis实现的BlogDao,其他的完全不需要变化。


同时之前SpringJDBC需要的数据源dataSource,与现在MyBatis使用的数据源dataSource组件配置完全一样。


Spring将功能、模块、类库等都化为了组件,召之即来挥之即去,非常类似于工业标准件的概念,大大提高了生产效率。


而为何我们广泛的采用了MyBatis、SpringJDBC等标准件,而不是自行开发的组件呢,就是因为大厂出品,经过千锤百炼的验证了,成本低效率高。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2天前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
7 1
|
1天前
|
Java 数据库连接 数据库
大事件后端项目05-----springboot整合mybatis
大事件后端项目05-----springboot整合mybatis
大事件后端项目05-----springboot整合mybatis
|
3天前
|
Java 数据库连接 Spring
Spring 整合 MyBatis 底层源码解析
Spring 整合 MyBatis 底层源码解析
|
4天前
|
Java 数据库连接 数据库
Spring Boot 集成 MyBatis-Plus 总结
Spring Boot 集成 MyBatis-Plus 总结
|
6天前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
24 3
|
6天前
|
Java 程序员
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
19 1
|
10天前
|
Java 数据库连接 mybatis
在Spring Boot应用中集成MyBatis与MyBatis-Plus
在Spring Boot应用中集成MyBatis与MyBatis-Plus
46 5
|
10天前
|
Java 数据库连接 数据库
实现Spring Boot与MyBatis结合进行数据库历史数据的定时迁移
实现Spring Boot与MyBatis结合进行数据库历史数据的定时迁移
23 2
|
12天前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
37 2
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术