天天看点

Spring之路(32)–SpringMVC+SpringJDBC+jQuery+Bootstrap博客系统完整实例

1. 前情回顾

之前我们已经用SpringMVC+JSP+Boostrap+原生JDBC实现过博客系统。

然后我们将其改为了前后端分离的Spring Restful+jQuery+Bootstrap+原生JDBC实现的博客系统。

本篇我们将完整的实现一个Spring+SpringMVC+SpringJDBC+jQuery+Bootstrap的博客系统,说的很复杂,实际上后端还是Restful风格的API,前端还是通过jQuery调用后端,Bootstrap仅负责页面样式。

OK,通过本篇希望大家将之前的知识点都串起来,同时我们的项目规范上也更加贴近项目实战多一些。

OK,前情回顾完毕,开整~~

2. 概述

功能:很简单,就是实现博客的增删改查。

数据库:MySQL,表结构如下:

CREATE TABLE `blog` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '唯一标志',
  `title` varchar(255) DEFAULT '' COMMENT '标题',
  `author` varchar(255) DEFAULT '' COMMENT '作者姓名',
  `content` longtext COMMENT '内容',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8;      

项目分层:

视图层(Html+Bootstrap+jQuery),负责页面显示

控制层(Controller),负责接受页面请求,并调用服务层完成业务逻辑,最后返回数据

服务层(Service),负责调用数据访问层,完成对数据库的增删改查操作,并封装业务逻辑

数据访问层(DAO),负责操作数据库

3. 新建项目

新建Dynamic web project,项目名称【springjdbcblog】,然后将Spring相关jar包以及下面几个jar包放入lib目录下:

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 数据库连接池

4. 新建包及目录、文件

建立如下图项目结构:

Spring之路(32)–SpringMVC+SpringJDBC+jQuery+Bootstrap博客系统完整实例

5. 完整开发过程

本次我们按照从底层到外层的开发方式,也就是从数据对象–数据访问层–服务层–控制器层–视图页面的顺序。

5.1 封装数据对象

数据对象与数据库表是一一对应关系,根据表中的列设计数据对象类的属性即可,代码如下:

package org.maoge.sjblog.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
}
5.2 封装数据访问层,并注册为bean
我们将博客数据访问层封装为BlogDao,并通过@Repositoy注册为bean,然后通过@Autowired注入jdbcTemplate对象。
package org.maoge.sjblog.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.maoge.sjblog.xdo.BlogDo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
/**
 * @theme DAO--博客
 * @author maoge
 * @date 2020-01-29
 */
@Repository // 注册为组件
public class BlogDao {
    @Autowired // 自动注入
    private NamedParameterJdbcTemplate namedTemplate;
    /**
  * 新增
  */
    public void insert(BlogDo blog) {
  Map map = new HashMap<>();
  map.put("author", blog.getAuthor());
  map.put("content", blog.getContent());
  map.put("title", blog.getTitle());
  // 注意使用:xxx占位
  namedTemplate.update("insert into blog(author,content,title)values(:author,:content,:title)", map);
    }
    /**
  * 删除
  */
    public void delete(Long id) {
  Map map = new HashMap<>();
  map.put("id", id);
  namedTemplate.update("delete from blog where id =:id", map);
    }
    /**
  * 更新
  */
    public void update(BlogDo blog) {
  Map map = new HashMap<>();
  map.put("author", blog.getAuthor());
  map.put("content", blog.getContent());
  map.put("title", blog.getTitle());
  map.put("id", blog.getId());
  namedTemplate.update("update blog set author=:author,content=:content,title=:title where id=:id", map);
    }
    /**
  * 按id查询
  */
    public BlogDo getById(Long id) {
  Map map = new HashMap<>();
  map.put("id", id);
  return namedTemplate.queryForObject("select * from blog where id=:id", map, new RowMapper() {
    @Override
    public BlogDo mapRow(ResultSet rs, int rowNum) throws SQLException {
    BlogDo blog = new BlogDo();
    blog.setAuthor(rs.getString("author"));
    blog.setContent(rs.getString("content"));
    blog.setId(rs.getLong("id"));
    blog.setTitle(rs.getString("title"));
    return blog;
    }
  });
    }
    /**
  * 查询列表
  */
    public List getList() {
  return namedTemplate.query("select * from blog", new RowMapper() {
    @Override
    public BlogDo mapRow(ResultSet rs, int rowNum) throws SQLException {
    BlogDo blog = new BlogDo();
    blog.setAuthor(rs.getString("author"));
    blog.setContent(rs.getString("content"));
    blog.setId(rs.getLong("id"));
    blog.setTitle(rs.getString("title"));
    return blog;
    }
  });
    }
}      

5.3 编写服务类,封装对博客的操作方法

直接我们是在控制器中直接调用数据接口层,这种封装会导致当业务逻辑比较复杂时,控制器层会有很多操作代码。

实际上控制器层应该只负责接受输入,调用方法完成业务逻辑,然后返回结果。

DAO层方法只是简单的对数据源完成增删改查等操作,显然不足以支撑业务逻辑。

所以一般在控制器层和DAO层之间,有一个服务层,封装业务逻辑和对数据源的操作,此处编写一个BlogService类实现该部分功能。

package org.maoge.sjblog.service;
import java.util.List;
import org.maoge.sjblog.dao.BlogDao;
import org.maoge.sjblog.xdo.BlogDo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @theme 服务--博客
 * @author maoge
 * @date 2020-01-27
 */
@Service//替代@Component
public class BlogService {
    @Autowired // 自动注入BlogDao组件
    private BlogDao blogDao;
    /**
  * 获取博客列表
  */
    public List 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);
    }
}
5.4 编写控制器,提供http接口
然后我们编写BlogController,按照Restful风格提供http接口,代码如下:
package org.maoge.sjblog.controller;
import java.util.List;
import org.maoge.sjblog.service.BlogService;
import org.maoge.sjblog.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 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);
    }
}      

5.5 编写html页面,调用api接口完成操作

编写html页面,通过jQuery的ajax调用BlogController里面的api方法,代码如下:

integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">      
<div data-lake-id="8d84cce1d2d73cda9a0c92b50d1457d1">   integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></div><div data-lake-id="1e4744a3d77b91e92090251b05c740db">
</div><div data-lake-id="df4dccd8f0b00975076ca0b1c0159675"> //浏览博客</div><div data-lake-id="362df7f6715f96bd70acb9c2d04297df">   function viewBlogs() {</div><div data-lake-id="86d1b35904b82dffc404252d92dc3d2c">  var row = "";</div><div data-lake-id="16ce686e9734201f86af1a59752416e3">  //先清空表格</div><div data-lake-id="a778976977ad6bb0fa51569be9be63c8">  $('#blogTable').find("tr:gt(0)").remove();</div><div data-lake-id="01655a041ba4e3702a4b50cecead2a67">  $.ajax({</div><div data-lake-id="d3abd510e751ba4a303b05a3ae12a808">     type: "GET",</div><div data-lake-id="307e172b6eb415c09d5c280049099f8f">     url: "/restfulblog/blog",</div><div data-lake-id="1fbcd2ff429fd19be3fffbdd736ad8e7">    dataType: "json",</div><div data-lake-id="97bdffb2e0475a7dcbd1d6f75006073d">    contentType: "application/json; charset=utf-8",</div><div data-lake-id="4077b87a8785f2dafe784d470cc63da6">      success: function (res) {</div><div data-lake-id="75b9301abe37257725df3f142fdd5b88">    $.each(res, function (i, v) {</div><div data-lake-id="e3c2b88f03525f2a5333febc537a6777">        row = "<tr>";</div><div data-lake-id="92dbb591768c8854bc09838aeb411c2b">        row += "<td>" + v.id + "</td>";</div><div data-lake-id="bb755a3c5f03e508a23286e2b4821210">      row += "<td>" + v.title + "</td>";</div><div data-lake-id="97ff4a98d61e4869c7d9c0221cc7963c">       row += "<td>" + v.author + "</td>";</div><div data-lake-id="57aeb3cb9cd3c32b1d960875d0049a02">      row +=</div><div data-lake-id="644b1b84846cb7bcf90ec10e8e61a854">      "<td><a class='btn btn-primary btn-sm' href='#' οnclick='editBlog(" + v.id +</div><div data-lake-id="6713c7747ad4f23f413824d5b6612596">      ")'>编辑</a>";</div><div data-lake-id="e4ec78052fcf6424ff83748a6bd6f9d9">     row +=</div><div data-lake-id="cc8676ec47b88d7aef1d83c59fb37448">      "<a class='btn btn-danger btn-sm' href='#' οnclick='deleteBlog(" + v.id +</div><div data-lake-id="70f33cce11ffe6be6948d5afea77d49c">      ")'>删除</a></td>";</div><div data-lake-id="2378c649c3e253df0fe3c839f6086549">       row += "</tr>";</div><div data-lake-id="8e212ab99ddbab0145fb359d18e225c2">      $("#blogTable").append(row);</div><div data-lake-id="a34ae617d8ab021e198e9c017e2efdbf">    });</div><div data-lake-id="e41d1a1cc9c73391c14f908ff1b78789">   },</div><div data-lake-id="d3cbc05a3432ce6e54529a2e3b89f3f3">   error: function (err) {</div><div data-lake-id="dab5149ac0ef53fdef6ffea3e527feec">    console.log(err);</div><div data-lake-id="da22821ff3907af70d3bd4b26d89130c">      }</div><div data-lake-id="2d39541c45210f5447b283a8a9d88ffb">  });</div><div data-lake-id="503deeeb75ddbc98703d2a72bc500271">    }</div><div data-lake-id="742d87d69e858c96f33e6cf2720219f7">    //新增</div><div data-lake-id="ecd49182034852e2e5594e2d29641d9b"> function addBlog() {</div><div data-lake-id="335aa32ef7282caf6e47f0536229fee2">  $('#blogAddModal').modal('show');</div><div data-lake-id="66b24ff76a1b1fb9eb4e3df518c6732e">   }</div><div data-lake-id="c85456257bfbd45276cb86a610335fff">    //新增提交</div><div data-lake-id="b2c95880c661d41ab51a53600e4a3eb6">   function addBlogSubmit() {</div><div data-lake-id="2c43754e053ac98cc84a857ea872983e">  var data = {</div><div data-lake-id="9a46f738e42fab907738a69f1b61f092">      id: '',</div><div data-lake-id="d8e6c76f3e8102e70d45a2c526ae461b">      title: $("#blogAddModal input[name='title']").val(),</div><div data-lake-id="629ddd60886feb998ea798453dac9661">     author: $("#blogAddModal input[name='author']").val(),</div><div data-lake-id="afdb8fee5ec04b0de1c0af69ca1ba142">   content: $("#blogAddModal textarea[name='content']").val()</div><div data-lake-id="2fb100e149e63adde3b393a4a45bae8e">  };</div><div data-lake-id="23c364f864f0be89125782e00a3a5543">  $.ajax({</div><div data-lake-id="4447ab0c0b9eef82b6eca12e15350c6d">   type: "POST",</div><div data-lake-id="4fd820a32117b4872b6242336aa5c594">    url: "/restfulblog/blog",</div><div data-lake-id="4d8a9857940cac3ad5bd0542c5f75453">    //dataType: "json",</div><div data-lake-id="424ea2740a92a9d1815835f9794f985a">      contentType: "application/json; charset=utf-8",</div><div data-lake-id="dcf9037056052477ae252f56fe440c43">      data: JSON.stringify(data), //需要将对象转换为字符串提交</div><div data-lake-id="3524fd66846962dc6e3b61c30ef5ea24">      success: function () {</div><div data-lake-id="abc0fb5723192d11ebd5ea56cc72dac1">    //新增后重新加载</div><div data-lake-id="bf3402e2edc667e4d4a6b46a80377c08">    viewBlogs();</div><div data-lake-id="12afc8fe231d52811d3e78a498cd1f81">    //关闭弹窗</div><div data-lake-id="afe557c7bc61b5a51bb7ed0f560c9fc3">    $('#blogAddModal').modal('hide');</div><div data-lake-id="42f2de88dac6fb87efa91682c5e0913c">   },</div><div data-lake-id="a0447c0e8d0fa3fa228f9213efe47b7d">   error: function (err) {</div><div data-lake-id="8f4ac7d05bcad0954ba0f0c5a9d07f46">    console.log(err);</div><div data-lake-id="3bcaeaed59595e57e05b60898701077e">      }</div><div data-lake-id="bfb465a472b6da4ff976de455ff5d9c1">  });</div><div data-lake-id="bf17f9cd291c91c18f748be8aaa4331d">    }</div><div data-lake-id="10d8b6659941ce749113598b98b9e10d">    //编辑</div><div data-lake-id="0e7845c8ee686bc8659c98496fd442ab"> function editBlog(id) {</div><div data-lake-id="dcfd4c4475a4d2f61c0b586baa6dcf02">  //查询博客信息</div><div data-lake-id="fa3a88d714d98255f03f3a6738ad5c3a">  $.ajax({</div><div data-lake-id="269de9badad4e9933889230ec247af51">    type: "GET",</div><div data-lake-id="73a9a89f4fc5568915994154882026d5">     url: "/restfulblog/blog/" + id,</div><div data-lake-id="cc2342d6efc17bd6142190e1f2d2b104">      dataType: "json",</div><div data-lake-id="c0957374189595a3a5ead20c87adb034">    contentType: "application/json; charset=utf-8",</div><div data-lake-id="e9ea35e34033d805229329ced906c2cf">      success: function (res) {</div><div data-lake-id="7438c63f63856a43df9de8c1bfa7c3b1">    console.log(res);</div><div data-lake-id="723fb0bdc7380d71be5c0ca6db44f543">    //为编辑框赋值</div><div data-lake-id="fed562aeffd5487ba4e55330ba8675ea">    $("#blogEditModal input[name='id']").val(res.id);</div><div data-lake-id="85ccfecfb2f7208cff77ca5710c95a93">    $("#blogEditModal input[name='title']").val(res.title);</div><div data-lake-id="8f6e284394f40cfb44af76113a86da49">    $("#blogEditModal input[name='author']").val(res.author);</div><div data-lake-id="a855488d4ceaaae6f1023ce689d041cd">    $("#blogEditModal textarea[name='content']").val(res.content);</div><div data-lake-id="aea437e3911d2ef021ec46ad5afb096c">    //显示编辑弹窗</div><div data-lake-id="f264d3220fcd1ba6a1e8b1aade42d7f3">    $('#blogEditModal').modal('show');</div><div data-lake-id="7613d06c88b6731e3e23d5762c61c3bd">      },</div><div data-lake-id="27579461ba76e1196a86d5ae2df71205">   error: function (err) {</div><div data-lake-id="ade906ad360ad7bc799c88178f33d43d">    console.log(err);</div><div data-lake-id="f6a36cd1bbc41ba0905540b50c91df95">      }</div><div data-lake-id="8c32940b6754018499c247479a0c8f76">  });</div><div data-lake-id="3216a5bf0cef334a63b32eb60e724110">    }</div><div data-lake-id="0122d71cb87a5a7af380b590e3123b38">    //编辑提交</div><div data-lake-id="6ecb20a27672cf3b016c7071ca717b8b">   function editBlogSubmit() {</div><div data-lake-id="f0cc3a2671faf21eb4bc34bde3e55f31">  var data = {</div><div data-lake-id="acd186fe44069133223687c9016390b4">     id: $("#blogEditModal input[name='id']").val(),</div><div data-lake-id="1cdadc5a1ef5c1cf016d83e6b3bfc2bf">      title: $("#blogEditModal input[name='title']").val(),</div><div data-lake-id="9e9dd2a4de87f8324eee18f16e478caa">    author: $("#blogEditModal input[name='author']").val(),</div><div data-lake-id="9e9adcb650c1f7c574027e797a8ee841">      content: $("#blogEditModal textarea[name='content']").val()</div><div data-lake-id="de6b70919abeed987fbb5d9a5e5d14b0">  };</div><div data-lake-id="7c57ac6709b6b0f1b318e68ea7eb84db">  $.ajax({</div><div data-lake-id="55fdffac93edf6f921faf18c1f2d0dd0">      type: "PUT",</div><div data-lake-id="ae0c0e8839e925a5624114ab22e799a4">     url: "/restfulblog/blog/" + data.id,</div><div data-lake-id="9119d11d8c377bb91166e32cab9da8dd">     //dataType: "json",</div><div data-lake-id="deb6d83fbee93c5f4afd50264e39d320">      contentType: "application/json; charset=utf-8",</div><div data-lake-id="935e9f9d9fcf935363538d3e60b50429">      data: JSON.stringify(data), //需要将对象转换为字符串提交</div><div data-lake-id="075733e3f789ce12fe5dfc9ac0f333ee">      success: function () {</div><div data-lake-id="d6b28577b0659b9acf2f164177a259ed">    //新增后重新加载</div><div data-lake-id="2cb0528220ff134180d30808173cc410">    viewBlogs();</div><div data-lake-id="b54a7cad8ed330ef08fe1b6212f7bf44">    //关闭弹窗</div><div data-lake-id="0f016e9f2ebce0286585de30436f5034">    $('#blogEditModal').modal('hide');</div><div data-lake-id="1eb30ca1c5ba80f8a50b1f29fb98bcc7">      },</div><div data-lake-id="2f919090af9674d722a6d36787e41e58">   error: function (err) {</div><div data-lake-id="653e5d344ff383e9b314626544b66384">    console.log(err);</div><div data-lake-id="6abfff97e759b02707cbff677854127e">      }</div><div data-lake-id="5435dd5969c698654faf49221d5579da">  });</div><div data-lake-id="82c5e6ad0625af92436596ee04aa1971">    }</div><div data-lake-id="bf0d022319681560373e11fe51b4c56b">    //删除</div><div data-lake-id="dd6ca7d2f378188ffbdb5cb7c3870cd8"> function deleteBlog(id) {</div><div data-lake-id="075d3be4f739e635b4d7ff507685276e">  $.ajax({</div><div data-lake-id="5825b200cd410d9c3832a78fbf8813f1">   type: "DELETE",</div><div data-lake-id="e5969c93e25ef91704689c5a714c01e2">      url: "/restfulblog/blog/" + id,</div><div data-lake-id="7c43dc83293ccd618edd977ecab47944">      //dataType: "json",//由于删除方法无返回值,所以此处注释掉</div><div data-lake-id="c1a98fea960cdb7755b4c92c62310969">      contentType: "application/json; charset=utf-8",</div><div data-lake-id="76f1e50dd2390bf93fd3e6bd653f51fc">      success: function () {</div><div data-lake-id="bd24701b8d3423812cc4982dd363e4d3">    //删除后重新加载</div><div data-lake-id="78819c3d19d73be06f5527066cc7209c">    viewBlogs();</div><div data-lake-id="a385a6df64489d789e6c8f16dec3875c">    },</div><div data-lake-id="cfd6c8e8b411ec36fc78a6d435f1bf46">   error: function (err) {</div><div data-lake-id="c6f29c9611cb955de780c9634c44fcdb">    console.log(err);</div><div data-lake-id="0697b60f0c3b09dec621bc623a84a7c2">      }</div><div data-lake-id="f25774ce8ca790e5b6b6b90f4f0df86f">  });</div><div data-lake-id="e7f3f1c7697f9e81614b9cbb58e00b0a">    }</div><div data-lake-id="28221a67677735e12ae5ed120ecabcbb">      

5.6 编写springmvc-config.xml

上面我们使用到的bean包括:namedParameterJdbcTemplate、blogDao、blogService、blogController,此外namedParameterJdbcTemplate还需要注入dataSource。

其中blogDao、blogService、blogController是使用注解标识的,我们可以直接开启扫描即可。namedParameterJdbcTemplate和dataSource是Spring提供的类,我们需要在xml手工配置。

所以springmvc-config.xml编写如下:

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">
    
    
  base-package="org.maoge.sjblog" />
    
    
    
    
    
    
  class="com.alibaba.druid.pool.DruidDataSource">
 
    value="com.mysql.jdbc.Driver">
 
 
    value="jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&characterEncoding=utf-8">
 
 
    
    
    
  class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">      

5.7 编写web.xml

最后我们实现下web.xml,当web服务启动时配置好加载的DispatcherServlet及对应的容器配置信息。

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">
    springjdbcblog
    
 springmvc
 org.springframework.web.servlet.DispatcherServlet
 
    contextConfigLocation
    /WEB-INF/springmvc-config.xml
 
 1
    
    
 springmvc
 /*      

6. 测试

部署到Tomcat上启动,界面如下,还是不错滴。

哈哈,虽然跟之前一版的博客系统从界面上讲没任何差别,但是后端代码变化不少啊,数据库操作引擎已经由自定义的DbHelper变为SpringJDBC封装的NamedParameterJdbcTemplate,而且还使用了Druid这样先进滴数据库连接池,稳啊!