使用SpringBoot开发项目效率非常高,但需要熟练掌握Maven工具的使用技巧,SpringBoot的将所有需要集成的框架依赖都维护好了,我们只需要在POM中引用父POM文件即可,如果还需要集成其他框架,比如RabbitMQ,Dubbo,需要再添加依赖。如下案例演示如何使用SpringBoot完成一对多的博文管理案例。
一、新建Maven webapp项目(可以使用Eclipse,IntelliJ IDEA工具,甚至Editplus)
二、修改POM.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>Proj_Blog</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Proj_Blog Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- 父类POM文件 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<!-- SpringBoot启动Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- 支持在线开发部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.11</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>jconsole</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SpringBoot对JSP支持依赖 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<finalName>Proj_Blog</finalName>
</build>
</project>
三、在/src/main/resources目录下新建application.properties配置文件
#SpringBoot服务端口配置
server.port=6060
server.context-path=/
#spring.resources.static-locations=/css,/images,/img,/js
#SpringMVC JSP目录配置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
#Http编码配置
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
#Rabbitmq配置
#spring.rabbitmq.host=127.0.0.1
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#spring.rabbitmq.virtual-host=/
#数据源配置
spring.datasource.name=w1
spring.datasource.url=jdbc:mysql://localhost:3306/w1?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.maxActive=20
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
#Mybatis实体类配置
mybatis.mapper-locations=classpath:mapper/*.xml
#Dubbo 1.0.1配置
#spring.dubbo.appname=dubbo-consumer
#spring.dubbo.registry=zookeeper://192.168.137.1:2181
#spring.dubbo.protocol=dubbo
#spring.dubbo.port=20880
#日志配置
logging.file=d:/springboot.log
logging.level.com.test.mapper=INFO
logging.level.com.hk.servlet=DEBUG
logging.level.com.test.service.impl=DEBUG
四、设计博文对应的SQL
create table t_blog (id int auto_increment primary key,
name varchar(40),dt date,author varchar(40),
content varchar(500),status int,typeid int);
create table t_type(id int auto_increment primary key,
name varchar(40));
insert into t_type(name) values('Java');
insert into t_type(name) values('Android');
insert into t_type(name) values('Python');
insert into t_blog(name,dt,author,content,status,typeid)
values('Java','2018-08-08','Sun','Sun Java',0,1);
insert into t_blog(name,dt,author,content,status,typeid)
values('Android','2018-09-08','Sun','Sun Java',0,2);
五、在/src/main/resources目录下新建mapper文件夹,在mapper文件夹中新建mapper.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="com.test.blog.mapper.BlogMapper">
<select id="findBlog" resultType="com.test.blog.bean.BlogInfo">
select b.*,t.name typeName from t_blog b,t_type t where b.typeid=t.id
and (b.name like '%${query}%' or b.content like '%${query}%')
</select>
<select id="findBlogById" resultType="com.test.blog.bean.BlogInfo">
select b.*,t.name typeName from t_blog b,t_type t where b.typeid=t.id
and b.id=#{id}
</select>
<select id="findType" resultType="com.test.blog.bean.TypeInfo">
select t.* from t_type t
</select>
<insert id="saveBlog" parameterType="com.test.blog.bean.BlogInfo">
insert into t_blog(name,author,dt,status,typeid,content) values
(#{name},#{author},#{dt},#{status},#{typeId},#{content})
</insert>
<update id="updateBlog" parameterType="com.test.blog.bean.BlogInfo">
update t_blog set name#{name},author=#{author},dt=#{dt},status=#{status},
typeid=#{typeId},content=#{content} where id=#{id}
</update>
<delete id="deleteBlog" parameterType="Integer">
delete from t_blog where id=#{id}
</delete>
</mapper>
六、在/src/main目录下新建java文件夹,在/src/main/java新建Java Package com.test.blog.mapper
package com.test.blog.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.test.blog.bean.BlogInfo;
import com.test.blog.bean.TypeInfo;
@Mapper
public interface BlogMapper {
public List<BlogInfo> findBlog(@Param("query") String query);
public List<TypeInfo> findType();
public void saveBlog(BlogInfo bi);
public void updateBlog(BlogInfo bi);
public void deleteBlog(@Param("id") Integer id);
public BlogInfo findBlogById(@Param("id") Integer id);
}
七、在/src/main/java目录下新建Pakcage com.test.blog.service
package com.test.blog.service;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.test.blog.bean.BlogInfo;
import com.test.blog.bean.TypeInfo;
public interface IBlogService {
public List<BlogInfo> findBlog(String query);
public List<TypeInfo> findType();
public void saveBlog(BlogInfo bi);
public void updateBlog(BlogInfo bi);
public void deleteBlog(Integer id);
public BlogInfo findBlogById(Integer id);
}
八、在/src/main/java目录下新建Pakcage com.test.blog.service.impl
package com.test.blog.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.test.blog.bean.BlogInfo;
import com.test.blog.bean.TypeInfo;
import com.test.blog.mapper.BlogMapper;
import com.test.blog.service.IBlogService;
@Service //Component Resouce
public class BlogServiceImpl implements IBlogService{
@Autowired
private BlogMapper mapper;
@Override
@Transactional(readOnly=true)
public List<BlogInfo> findBlog(String query) {
return mapper.findBlog(query);
}
@Override
public List<TypeInfo> findType() {
return mapper.findType();
}
@Override
public void saveBlog(BlogInfo bi)
{
mapper.saveBlog(bi);
}
@Override
public void updateBlog(BlogInfo bi)
{
mapper.updateBlog(bi);
}
@Override
public void deleteBlog(Integer id)
{
mapper.deleteBlog(id);
}
@Override
public BlogInfo findBlogById(Integer id)
{
return mapper.findBlogById(id);
}
}
九、在/src/main/java目录下新建Pakcage com.test.blog.ctrl
package com.test.blog.ctrl;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.test.blog.PageUtil;
import com.test.blog.bean.BlogInfo;
import com.test.blog.bean.TypeInfo;
import com.test.blog.service.IBlogService;
@Controller
public class BlogCtrl {
@Autowired
private IBlogService serv;
/**
* 跳转到列表的URL对应方法
* @param req 请求对象
* @param page 当前页参数
* @param rows 每页显示记录数
* @return
*/
@RequestMapping("/init")
public String init(HttpServletRequest req,Integer page,Integer rows)
{
if(page == null)
page = 1;
if(rows == null)
rows = 4;
//取查询条件
String query = req.getParameter("query");
//1.定义执行SQL结果集的指令
PageHelper.startPage(page, rows);
//2.执行Mybatis查询
List<BlogInfo> lst = serv.findBlog(query);
//3.封装PageInfo对象
PageInfo pi = new PageInfo(lst);
List pageList = pi.getList();
Long total = pi.getTotal();
String url = "/init";
PageUtil pu = new PageUtil(url,page,rows,total);
String htmlPage = pu.toHtml();
req.setAttribute("list", pageList);
req.setAttribute("pageHtml", htmlPage);
req.setAttribute("query", query);
return "blog2";
}
/**
* 当前台点击新建博文,跳转的URL对应的方法
* @param req 请求对象
* @return
*/
@RequestMapping("/addblog")
public String addblog(HttpServletRequest req)
{
List<TypeInfo> types = serv.findType();
req.setAttribute("types", types);
return "addblog";
}
/**
* 当前台点击保存博文,对应URL的方法
* @param req 请求对象
* @param bi 从请求参数中包装BlogInfo对象
* @return
*/
@RequestMapping("/saveblog")
public String saveblog(HttpServletRequest req,BlogInfo bi)
{
Integer id = bi.getId();
if(id == null)//id为空,代表新建博文
serv.saveBlog(bi);
else//id不为空,代表修改博文
serv.updateBlog(bi);
//跳转到分页列表
String page = init(req,1,4);
return page;
}
/**
* 删除博文的方法
* @param req 请求对象
* @param ids 删除的ID,ID以逗号分隔
* @return
*/
@ResponseBody
@RequestMapping("/deleteblog")
public boolean deleteblog(HttpServletRequest req,Integer[] ids)
{
for(Integer id:ids)
{
if(id != null)
serv.deleteBlog(id);
}
return true;
}
/**
* 当前台点击修改博文时,对应URL的方法
* @param req 请求对象
* @param id 从前台传入的ID
* @return
*/
@RequestMapping("/editblog")
public String editblog(HttpServletRequest req,Integer id)
{
BlogInfo bi = serv.findBlogById(id);
req.setAttribute("blog", bi);
List<TypeInfo> lst = serv.findType();
for(TypeInfo t:lst)
{
if(bi.getTypeId().equals(t.getId().toString()))
{
t.setSelected("selected");
}
}
req.setAttribute("types", lst);
return "addblog";
}
}
十、在/src/main/java目录下新建Pakcage com.test.blog.bean,新建实体类
package com.test.blog.bean;
import java.io.Serializable;
import java.sql.Date;
public class BlogInfo implements Serializable{
private Integer id = null;
private String name = null;
private Date dt = null;
private String author = null;
private String content = null;
private String typeId = null;
private Integer status = null;
private String typeName = null;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDt() {
return dt;
}
public void setDt(Date dt) {
this.dt = dt;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}
package com.test.blog.bean;
import java.io.Serializable;
import java.sql.Date;
public class TypeInfo implements Serializable{
private Integer id = null;
private String name = null;
private String selected = "";
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSelected() {
return selected;
}
public void setSelected(String selected) {
this.selected = selected;
}
}
十一、在/src/main/webapp新建jscss目录,设计CSS/JS
@charset "utf-8";
/* CSS Document */
body{
margin:0 auto;
padding:0;
font-family:'Microsoft YaHei', arial, tahoma, \5b8b\4f53, sans-serif;
font-size: 14px;
}
a {
text-decoration:none;
color:black;
}
div{
margin:0 auto;
}
#pagediv{
margin:0 auto;
text-align:center;
valign:middle;
background-color: yellow;
height:30px;
line-height: 30px;
border:1px solid black
}
table {
width:100%;
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table tr:nth-child(odd) td{
background: #ccc;
}
table tr:hover td{
background: pink;
}
table th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: yellow;
}
table th {
font-size:15px;
color:blue;
}
table td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
十二、设计列表页面blog.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="/jscss/base.css">
<script type="text/javascript" src="/jscss/jquery.min.js"></script>
<title>博文列表</title>
<script>
function addblog()
{
window.open("/addblog","_self");
//window.open("/addblog","_blank");
//location.href="/addblog";
}
function deleteblog()
{
var delid='';
$("input[name='chkid']:checked").each(function(){
delid=delid+this.value+',';
});
$.ajax({
url:'/deleteblog?ids='+delid,
success:function(data)
{
alert(data);
window.open("/init","_self");
}
})
}
function selectAll()
{
$("input[name='chkid']").each(function(){
this.checked=!this.checked;
});
}
function doquery()
{
listfrm.submit();
}
</script>
</head>
<body>
<form id="listfrm" action="/init">
<input type="text" id="query" name="query" value="${query}"/>
<input type="button" value="查询" onclick="doquery()"/>
<table>
<tr>
<th><input type="checkbox" id="chkall" name="chkall" onclick="selectAll()"/>编号</th>
<th>名称</th>
<th>作者</th>
<th>分类</th>
<th>日期</th>
<th>状态</th>
<th>内容</th>
<th>操作</th>
</tr>
<c:forEach items="${list }" var="blog">
<tr>
<td><input type="checkbox" id="chkid" name="chkid" value="${blog.id }"/>${blog.id }</td>
<td>${blog.name }</td>
<td>${blog.author }</td>
<td>${blog.typeName }</td>
<td>${blog.dt }</td>
<td>${blog.status }</td>
<td>${blog.content }</td>
<td><a href="/editblog?id=${blog.id }">修改</a></td>
</tr>
</c:forEach>
</table>
${pageHtml}
<input type="button" value="添加博文" onclick="addblog()"/>
<input type="button" value="删除博文" onclick="deleteblog()"/>
</form>
</html>
添加页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="/jscss/base.css">
<script type="text/javascript" src="/jscss/jquery.min.js"></script>
<title>博文列表</title>
<script>
function dosave()
{
blogfrm.submit();
}
function dolist()
{
location.href="/init";
}
</script>
</head>
<body>
<form id="blogfrm" action="/saveblog">
<input type="hidden" id="status" name="status" value="${blog.status}"/>
<table>
<tr>
<td>博文名称</td>
<td><input type="text" id="name" name="name" value="${blog.name}"></td>
</tr>
<tr>
<td>博文作者</td>
<td><input type="text" id="author" name="author" value="${blog.author}"></td>
</tr>
<tr>
<td>博文时间</td>
<td><input type="text" id="dt" name="dt" value="${blog.dt}"></td>
</tr>
<tr>
<td>博文内容</td>
<td><input type="text" id="content" name="content" value="${blog.content}"></td>
</tr>
<tr>
<td>博文分类</td>
<td>
<select id="typeId" name="typeId">
<c:forEach items="${types }" var="t">
<option value="${t.id }" ${t.selected }>${t.name }</option>
</c:forEach>
</select>
</td>
</tr>
</table>
<input type="button" value="提交" onclick="dosave()"/>
<input type="button" value="返回" onclick="dolist()"/>
</form>
</html>
十三、分页工具类
package com.test.blog;
public class PageUtil {
private Integer page = 1;//默认显示第一页
private Integer rows = 4;//每页显示记录数
private Long total = null;//总行数
private String url = null;//点击页码跳转url
public PageUtil(String url,Integer page,Integer rows,Long total)
{
this.url = url;
this.page = page;
this.rows = rows;
this.total = total;
}
public String toHtml()
{
StringBuffer sb = new StringBuffer();
//计算总页数
int pages = 0;
if(total % rows == 0)
pages = total.intValue() / rows;
else
pages = (total.intValue() / rows) + 1;
sb.append("<div id='pagediv'>\r\n");
String firstUrl = null;
if(url.indexOf("?")>0)
firstUrl = url + "&page=1&rows="+rows;
else
firstUrl = url + "?page=1&rows="+rows;
sb.append("<a href='"+firstUrl+"'>首页</a>\r\n");
String backUrl = null;
if(url.indexOf("?")>0)
backUrl = url + "&page="+(page==1?1:(page-1))+"&rows="+rows;
else
backUrl = url + "?page="+(page==1?1:(page-1))+"&rows="+rows;
sb.append("<a href='"+backUrl+"'>上一页</a>\r\n");
for(int i=1;i<=pages;i++)
{
String pageUrl = null;
if(url.indexOf("?")>0)
pageUrl = url + "&page="+i+"&rows="+rows;
else
pageUrl = url + "?page="+i+"&rows="+rows;
if(i == page)
sb.append("<a href='"+pageUrl+"'><b><font color='red'>"+i+"</font></b></a>\r\n");
else
sb.append("<a href='"+pageUrl+"'>"+i+"</a>\r\n");
}
String nextUrl = null;
if(url.indexOf("?")>0)
nextUrl = url + "&page="+(page==pages?pages:(page+1))+"&rows="+rows;
else
nextUrl = url + "?page="+(page==pages?pages:(page+1))+"&rows="+rows;
sb.append("<a href='"+nextUrl+"'>下一页</a>\r\n");
String lastUrl = null;
if(url.indexOf("?")>0)
lastUrl = url + "&page="+pages+"&rows="+rows;
else
lastUrl = url + "?page="+pages+"&rows="+rows;
sb.append("<a href='"+lastUrl+"'>尾页</a>\r\n");
sb.append(" 第"+page+"/"+pages+"页\r\n");
sb.append(" 共"+total+"条记录\r\n");
sb.append("</div>\r\n");
return sb.toString();
}
}
十四、SpringBoot启动类
package com.test.blog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Starter {
public static void main(String[] args) {
SpringApplication.run(Starter.class, args);
}
}
界面效果