心血来潮,没事的时候想写一个自己的日记小程序(也叫帖子小程序)把,主要会实现前端页面和简单的后端接口:
大概页面如下:
目前前端页面不全,等我写完在补全吧,大概就这个调了,哈哈~
这篇先实现后端接口:新建一个项目,选择Spring Initializr
,项目名自定义。
实现的目录结构:
建表
CREATE TABLE `tb_post` (
`post_id` int(10) NOT NULL AUTO_INCREMENT,
`post_title` varchar(20) NOT NULL,
`post_content` varchar(200) NOT NULL,
`post_type` varchar(5) NOT NULL,
`priority` int(10) NOT NULL,
`create_time` datetime NOT NULL,
`last_time` datetime NOT NULL,
PRIMARY KEY (`post_id`)
) DEFAULT CHARSET=utf8;
pom.xml
项目需要的坐标依赖:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liyingxia</groupId>
<artifactId>post</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>post</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
应用启动入口
PostApplication:
package com.liyingxia.post;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PostApplication {
public static void main(String[] args) {
SpringApplication.run(PostApplication.class, args);
System.out.println("启动成功~");
}
}
配置类
DataSourceConfig:
package com.liyingxia.post.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.beans.PropertyVetoException;
/**
* @Package: com.liyingxia.post.config
* @Description: 配置datasource到ioc容器里面
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:42
*/
@Configuration
// 配置mybatis mapper的扫描路径
@MapperScan("com.liyingxia.post.dao")
public class DataSourceConfig {
@Value("${jdbc.driver}")
private String jdbcDriver;
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
/**
* 生成与spring-dao.xml对应的bean dataSource
*
* @return
* @throws PropertyVetoException
*/
@Bean(name = "dataSource")
public ComboPooledDataSource createDataSource() throws PropertyVetoException {
// 生成datasource实例
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 跟配置文件一样设置以下信息
// 驱动
dataSource.setDriverClass(jdbcDriver);
// 数据库连接URL
dataSource.setJdbcUrl(jdbcUrl);
// 设置用户名
dataSource.setUser(jdbcUsername);
// 设置用户密码
dataSource.setPassword(jdbcPassword);
// 配置c3p0连接池的私有属性
// 连接池最大线程数
dataSource.setMaxPoolSize(30);
// 连接池最小线程数
dataSource.setMinPoolSize(10);
// 关闭连接后不自动commit
dataSource.setAutoCommitOnClose(false);
// 连接超时时间
dataSource.setCheckoutTimeout(10000);
// 连接失败重试次数
dataSource.setAcquireRetryAttempts(2);
return dataSource;
}
}
SessionFactoryConfig:
package com.liyingxia.post.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import javax.sql.DataSource;
import java.io.IOException;
/**
* @Package: com.liyingxia.post.config
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:43
*/
@Configuration
public class SessionFactoryConfig {
// mybatis-config.xml.xml配置文件的路径
private static String mybatisConfigFile;
@Value("${mybatis_config_file}")
public void setMybatisConfigFile(String mybatisConfigFile) {
SessionFactoryConfig.mybatisConfigFile = mybatisConfigFile;
}
// mybatis mapper文件所在路径
private static String mapperPath;
@Value("${mapper_path}")
public void setMapperPath(String mapperPath) {
SessionFactoryConfig.mapperPath = mapperPath;
}
// 实体类所在的package
@Value("${type_alias_package}")
private String typeAliasPackage;
@Autowired
private DataSource dataSource;
/**
* 创建sqlSessionFactoryBean 实例 并且设置configtion 设置mapper 映射路径 设置datasource数据源
*
* @return
* @throws IOException
*/
@Bean(name = "sqlSessionFactory")
public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 设置mybatis configuration 扫描路径
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFile));
// 添加mapper 扫描路径
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources(packageSearchPath));
// 设置dataSource
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置typeAlias 包扫描路径
sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasPackage);
return sqlSessionFactoryBean;
}
}
TransactionManagermentConfig:
package com.liyingxia.post.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.sql.DataSource;
/**
* @Package: com.liyingxia.post.config
* @Description: 对标spring-service里面的transactionManager,继承TransactionManagementConfigurer是因为开启annotation-driven
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:47
*/
@Configuration
/**
* 使用:
* 1. 首先使用注解 @EnableTransactionManagement 开启事务支持后
* 2. 在Service方法上添加注解 @Transactional 即可
*/
@EnableTransactionManagement
public class TransactionManagementConfig implements TransactionManagementConfigurer {
@Autowired
// 注入DataSourceConfiguration里边的dataSource,通过createDataSource()获取
private DataSource dataSource;
@Override
/**
* 关于事务管理,需要返回PlatformTransactionManager的实现
*/
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}
}
controller
PostController:
package com.liyingxia.post.controller;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.liyingxia.post.entity.Post;
import com.liyingxia.post.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Package: com.liyingxia.post.controller
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:57
*/
@RestController
@RequestMapping("/manager")
public class PostController {
@Autowired
private PostService postService;
/**
* 获取所有列表信息
* @return
*/
@RequestMapping(value = "/list",method = RequestMethod.GET)
private Map<String,Object> listPost() {
Map<String,Object> map = new HashMap<String, Object>();
List<Post> list = new ArrayList<Post>();
// 获取帖子列表
list = postService.getPostList();
map.put("postList",list);
return map;
}
/**
* 根据id 查询对应的列表
* @param postId
* @return
*/
@RequestMapping(value = "/postId", method = RequestMethod.GET)
private Map<String,Object> getPostId(Integer postId) {
Map<String,Object> map = new HashMap<String,Object>();
// 获取帖子信息
Post post = postService.getPostById(postId);
map.put("post",post);
return map;
}
/**
* 新增帖子
* @param post
* @return
* @throws JsonParseException
* @throws JsonMappingException
* @throws IOException
*/
@RequestMapping(value = "/addPost", method = RequestMethod.POST)
private Map<String,Object> addPost(@RequestBody Post post) throws JsonParseException,JsonMappingException,IOException {
Map<String,Object> map = new HashMap<String,Object>();
// 添加贴子信息
map.put("success",postService.addPost(post));
return map;
}
/**
* 修改帖子
* @param post
* @return
* @throws JsonMappingException
* @throws JsonParseException
* @throws IOException
*/
@RequestMapping(value = "/modify", method = RequestMethod.PUT)
private Map<String,Object> modifyPost(@RequestBody Post post) throws JsonMappingException,JsonParseException,IOException {
Map<String,Object> map = new HashMap<String,Object>();
// 修改贴子信息
map.put("success",postService.modifyPost(post));
return map;
}
/**
* 删除根据id帖子
* @param postId
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
private Map<String,Object> deletePost(Integer postId) {
Map<String,Object> map = new HashMap<String,Object>();
// 删除信息
map.put("success",postService.deletePost(postId));
return map;
}
}
dao
PostDao:
package com.liyingxia.post.dao;
import com.liyingxia.post.entity.Post;
import java.util.List;
/**
* @Package: com.liyingxia.post.dao
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:52
*/
public interface PostDao {
/**
* 列出帖子列表
* @return
*/
List<Post> queryPost();
/**
* 根据id获取帖子
* @param postId
* @return
*/
Post queryPostById(int postId);
/**
* 插入帖子信息
* @param post
* @return
*/
int insertPost(Post post);
/**
* 更新帖子信息
* @param post
* @return
*/
int updatePost(Post post);
/**
* 根据id 删除帖子信息
* @param postId
* @return
*/
int deletePost(int postId);
}
entity
Post:
package com.liyingxia.post.entity;
import java.util.Date;
/**
* @Package: com.liyingxia.post.entity
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:53
*/
public class Post {
// 主键ID
private Integer postId;
// 标题
private String postTitle;
// 内容
private String postContent;
// 类型
private String postType;
// 权重,越大越排前显示
private Integer priority;
// 创建时间
private Date createTime;
// 更新时间
private Date lastTime;
public Integer getPostId() {
return postId;
}
public void setPostId(Integer postId) {
this.postId = postId;
}
public String getPostTitle() {
return postTitle;
}
public void setPostTitle(String postTitle) {
this.postTitle = postTitle;
}
public String getPostContent() {
return postContent;
}
public void setPostContent(String postContent) {
this.postContent = postContent;
}
public String getPostType() {
return postType;
}
public void setPostType(String postType) {
this.postType = postType;
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getLastTime() {
return lastTime;
}
public void setLastTime(Date lastTime) {
this.lastTime = lastTime;
}
}
service
PostService:
package com.liyingxia.post.service;
import com.liyingxia.post.entity.Post;
import java.util.List;
/**
* @Package: com.liyingxia.post.service
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:55
*/
public interface PostService {
/**
* 获取帖子列表
* @return
*/
List<Post> getPostList();
/**
* 通过id获取帖子信息
* @param postId
* @return
*/
Post getPostById(int postId);
/**
* 新增帖子信息
* @param post
* @return
*/
boolean addPost(Post post);
/**
* 修改帖子信息
* @param post
* @return
*/
boolean modifyPost(Post post);
/**
* 通过id删除帖子信息
* @param postId
* @return
*/
boolean deletePost(int postId);
}
PostServiceImpl:
package com.liyingxia.post.service.impl;
import com.liyingxia.post.dao.PostDao;
import com.liyingxia.post.entity.Post;
import com.liyingxia.post.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @Package: com.liyingxia.post.service.impl
* @Description:
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:55
*/
@Service
public class PostServiceImpl implements PostService {
@Autowired
private PostDao postDao;
@Override
public List<Post> getPostList() {
// 返回所有的帖子信息
return postDao.queryPost();
}
@Override
public Post getPostById(int postId) {
return postDao.queryPostById(postId);
}
@Transactional
@Override
public boolean addPost(Post post) {
// 控制判断,
if ((post.getPostTitle() != null && !"".equals(post.getPostTitle()))
&& post.getPostContent() != null && !"".equals(post.getPostContent())
&& post.getPriority() != null && !"".equals(post.getPriority())
&& post.getPostType() != null && !"".equals(post.getPostType())
) {
// 设置创建时间
post.setCreateTime(new Date());
post .setLastTime(new Date());
try{
int effectedNum = postDao.insertPost(post);
if (effectedNum > 0) {
return true;
} else {
throw new RuntimeException("添加失败");
}
} catch (Exception e) {
throw new RuntimeException("添加失败" + e.toString());
}
} else {
throw new RuntimeException("请填写正确的信息");
}
}
@Override
public boolean modifyPost(Post post) {
// 控制判断,postId不为空
if (post.getPostId() !=null && post.getPostId() > 0) {
//设置修改时间
post.setLastTime(new Date());
try{
int effectedNum = postDao.updatePost(post);
if (effectedNum > 0) {
return true;
} else {
throw new RuntimeException("更新信息失败!");
}
}catch (Exception e) {
throw new RuntimeException("更新信息失败!" + e.toString());
}
} else {
throw new RuntimeException("请填写正确的信息");
}
}
@Transactional
@Override
public boolean deletePost(int postId) {
if (postId > 0) {
try {
// 删除帖子信息
int effectedNum = postDao.deletePost(postId);
if (effectedNum > 0) {
return true;
} else {
throw new RuntimeException("删除信息失败!");
}
} catch (Exception e) {
throw new RuntimeException("删除信息失败:" + e.toString());
}
} else {
throw new RuntimeException("id不能为空!");
}
}
}
handler
GlobalExceptionHandler:
package com.liyingxia.post.handler;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* @Package: com.liyingxia.post.handler
* @Description: 统一异常处理类
* @Author: liyingxia
* @CreateDate: 2021/11/15 9:53
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String, Object> exceptionHandler(HttpServletRequest req, Exception e) throws Exception {
Map<String, Object> modelMap = new HashMap<String, Object>();
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
}
Mapper
PostMapper:
<?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.liyingxia.post.dao.PostDao">
<select id="queryPost" resultType="com.liyingxia.post.entity.Post">
SELECT post_id, post_title,post_content,post_type,priority, create_time, last_time
FROM tb_post
ORDER BY priority
DESC
</select>
<select id="queryPostById" resultType="com.liyingxia.post.entity.Post">
SELECT post_id, post_title,post_content,post_type,priority, create_time, last_time
FROM tb_post
WHERE
post_id=#{postId}
</select>
<insert id="insertPost" useGeneratedKeys="true" keyProperty="postId"
keyColumn="post_id" parameterType="com.liyingxia.post.entity.Post">
INSERT INTO
tb_post(post_title,post_content,post_type,priority,create_time,last_time)
VALUES
(#{postTitle},#{postContent},#{postType},#{priority},#{createTime},#{lastTime})
</insert>
<update id="updatePost" parameterType="com.liyingxia.post.entity.Post">
update tb_post
<set>
<if test="postTitle != null">post_title=#{postTitle},</if>
<if test="postContent != null">post_content=#{postContent},</if>
<if test="postType != null">post_type=#{postType},</if>
<if test="priority != null">priority=#{priority},</if>
<if test="lastTime != null">last_time=#{lastTime}</if>
</set>
where post_id=#{postId}
</update>
<delete id="deletePost">
DELETE FROM
tb_post
WHERE
post_id =
#{postId}
</delete>
</mapper>
mapper标签的namespace属性为该映射文件对应Dao接口类。
-
update
标签用于更新操作,id
属性为对应方法名
insert
标签用于插入操作,keyColumn
和select
语句中的表名相对应的实体类的字段对应,keyProperty
和insert
语句中的values
内的参数一致,也就是和insert
语句中的表的对应实体类的字段一致,才可以通过反射完成,paramerType
属性为传入方法的参数类型,标签体为操作sql
,#{x}
为传入参数entity
的x
属性。useGeneratedKeys="true"
使用jdbc的getGeneratedKeys
获取数据库自增主键值。 -
select
标签用于查询操作
,id
属性对应方法名
。 -
delete
标签用于删除操作
,id
属性对应方法名
。
application.properties:
server.port=8080
##加入/post前缀
#server.context-path=/post
#DataSource
#数据库驱动
jdbc.driver=com.mysql.jdbc.Driver
#数据库链接
jdbc.url=jdbc:mysql://localhost:3306/mdatabase?useUnicode=true&characterEncoding=utf8&useSSL=false
#数据库用户名
jdbc.username=root2
#数据库密码
jdbc.password=123456
#Mybatis
mybatis_config_file=mybatis-config.xml
mapper_path=/mapper/**.xml
type_alias_package=com.liyingxia.post.entity
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>
<!-- 配置全局属性 -->
<settings>
<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 使用列标签替换列别名 默认:true -->
<setting name="useColumnLabel" value="true" />
<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
</configuration>
postman测试
保证本地有MySQL数据库服务器运行状态下,运行PostApplication应用程序入口,baseUrl:http://localhost:8080/manager/
获取列表:
新增:
更新:
删除: