赞
踩
SpringBoot Spring SpringMVC MyBatis Redis Kakfa Elasticsearch Spring Security Spring Actator
在Spring Boot Initializr中或者Idea中初始化一个SpringBoot项目并导出
使用Idea打开导出的项目
各个层之间的关系如下
在Maven Repository搜索MySql Maven配置文件,在resources文件包内的pom.xml文件中导入相关的配置文件依赖,并在application.properties文件中配置相关的参数。
# ServerProperties server.port=8080 server.servlet.context-path=/community # ThymeleafProperties spring.thymeleaf.cache=false # DataSourceProperties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/community?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong #数据库的名称、密码等 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.type=com.zaxxer.hikari.HikariDataSource #最大连接数、超时时间等 spring.datasource.hikari.maximum-pool-size=15 spring.datasource.hikari.minimum-idle=5 spring.datasource.hikari.idle-timeout=30000 # MybatisProperties #mapper扫描路径 mybatis.mapper-locations=classpath:mapper/*.xml #在communtiy下创建实体类 mybatis.type-aliases-package=com.nowcoder.community.entity mybatis.configuration.useGeneratedKeys=true mybatis.configuration.mapUnderscoreToCamelCase=true
在community文件下创建config entity文件包,在resources文件下创建mapper文件包
在entity文件下创建User类
public class User { private int id; private String username; private String password; private String salt; private String email; private int type; private int status; private String activationCode; private String headerUrl; private Date createTime; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getActivationCode() { return activationCode; } public void setActivationCode(String activationCode) { this.activationCode = activationCode; } public String getHeaderUrl() { return headerUrl; } public void setHeaderUrl(String headerUrl) { this.headerUrl = headerUrl; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + ''' + ", password='" + password + ''' + ", salt='" + salt + ''' + ", email='" + email + ''' + ", type=" + type + ", status=" + status + ", activationCode='" + activationCode + ''' + ", headerUrl='" + headerUrl + ''' + ", createTime=" + createTime + '}'; } }
在dao文件下创建UserMapper接口访问数据库
@Mapper public interface UserMapper { User selectById(int id); User selectByName(String username); User selectByEmail(String email); int insertUser(User user); int updateStatus(int id, int status); int updateHeader(int id, String headerUrl); int updatePassword(int id, String password); }
使用Mapper注解,并在mapper文件下创建user-mapp.xml,使得方法与Sql语句相关联,Mybatis 的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.nowcoder.community.dao.UserMapper"> <sql id="insertFields"> username, password, salt, email, type, status, activation_code, header_url, create_time </sql> <sql id="selectFields"> id, username, password, salt, email, type, status, activation_code, header_url, create_time </sql> <select id="selectById" resultType="User"> select <include refid="selectFields"></include> from user where id = #{id} </select> <select id="selectByName" resultType="User"> select <include refid="selectFields"></include> from user where username = #{username} </select> <select id="selectByEmail" resultType="User"> select <include refid="selectFields"></include> from user where email = #{email} </select> <insert id="insertUser" parameterType="User" keyProperty="id"> insert into user (<include refid="insertFields"></include>) values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime}) </insert> <update id="updateStatus"> update user set status = #{status} where id = #{id} </update> <update id="updateHeader"> update user set header_url = #{headerUrl} where id = #{id} </update> <update id="updatePassword"> update user set password = #{password} where id = #{id} </update> </mapper>
可以使用@Test注解测试相关方法是否正常使用
在Entity创建DiscussPost类,用于表示发送的相关数据,并在dao文件中创建DiscussPostMapper接口
public class DiscussPost { private int id; private int userId; private String title; private String content; private int type; private int status; private Date createTime; private int commentCount; private double score; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public int getCommentCount() { return commentCount; } public void setCommentCount(int commentCount) { this.commentCount = commentCount; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } @Override public String toString() { return "DiscussPost{" + "id=" + id + ", userId=" + userId + ", title='" + title + ''' + ", content='" + content + ''' + ", type=" + type + ", status=" + status + ", createTime=" + createTime + ", commentCount=" + commentCount + ", score=" + score + '}'; } } @Mapper public interface DiscussPostMapper { // 考虑到后期分页功能加入offset 和 limit变量 // @Param注解用于给参数取别名, // 如果只有一个参数,并且在<if>里使用,则必须加别名. List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit); int selectDiscussPostRows(@Param("userId") int userId); }
在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.nowcoder.community.dao.DiscussPostMapper"> <sql id="selectFields"> id, user_id, title, content, type, status, create_time, comment_count, score </sql> <select id="selectDiscussPosts" resultType="DiscussPost"> select <include refid="selectFields"></include> from discuss_post where status != 2 <if test="userId!=0"> and user_id = #{userId} </if> order by type desc, create_time desc limit #{offset}, #{limit} </select> <select id="selectDiscussPostRows" resultType="int"> select count(id) from discuss_post where status != 2 <if test="userId!=0"> and user_id = #{userId} </if> </select> </mapper>
在service文件下创建DiscussPostService类,用于服务层使用(使用@Service注解)
@Service
public class DiscussPostService {
@Autowired
private DiscussPostMapper discussPostMapper;
public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit) {
return discussPostMapper.selectDiscussPosts(userId, offset, limit);
}
public int findDiscussPostRows(int userId) {
return discussPostMapper.selectDiscussPostRows(userId);
}
}
将静态资源(css image js等文件)放到static文件下,将模板文件(site index.html)放到templates文件下。
接下来开发视图层,新建一个HomeController在controller文件下使用@Controller注解
//Controller访问路径可以省略 @Controller public class HomeController { //注入对象 @Autowired private DiscussPostService discussPostService; @Autowired private UserService userService; //使用GET方法 @RequestMapping(path = "/index", method = RequestMethod.GET) List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit()); List<Map<String, Object>> discussPosts = new ArrayList<>(); if (list != null) { for (DiscussPost post : list) { Map<String, Object> map = new HashMap<>(); map.put("post", post); User user = userService.findUserById(post.getUserId()); map.put("user", user); discussPosts.add(map); } } model.addAttribute("discussPosts", discussPosts); return "/index"; } }
更改Index.html文件,使用Thymeleaf对其中相对路径进行更改,并显示相关的帖子。
<ul class="list-unstyled"> <li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}"> <a href="site/profile.html"> <img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="用户头像" style="width:50px;height:50px;"> </a> <div class="media-body"> <h6 class="mt-0 mb-3"> <a href="#" th:utext="${map.post.title}">备战春招,面试刷题跟他复习,一个月全搞定!</a> <span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}">置顶</span> <span class="badge badge-secondary bg-danger" th:if="${map.post.status==1}">精华</span> </h6> <div class="text-muted font-size-12"> <u class="mr-3" th:utext="${map.user.username}">寒江雪</u> 发布于 <b th:text="${#dates.format(map.post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b> <ul class="d-inline float-right"> <li class="d-inline ml-2">赞 11</li> <li class="d-inline ml-2">|</li> <li class="d-inline ml-2">回帖 7</li> </ul> </div> </div> </li> </ul>
完整的HTML文件如下:
<!doctype html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous"> <link rel="stylesheet" th:href="@{/css/global.css}" /> <title>牛客网-首页</title> </head> <body> <div class="nk-container"> <!-- 头部 --> <header class="bg-dark sticky-top"> <div class="container"> <!-- 导航 --> <nav class="navbar navbar-expand-lg navbar-dark"> <!-- logo --> <a class="navbar-brand" href="#"></a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <!-- 功能 --> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item ml-3 btn-group-vertical"> <a class="nav-link" href="index.html">首页</a> </li> <li class="nav-item ml-3 btn-group-vertical"> <a class="nav-link position-relative" href="site/letter.html">消息<span class="badge badge-danger">12</span></a> </li> <li class="nav-item ml-3 btn-group-vertical"> <a class="nav-link" href="site/register.html">注册</a> </li> <li class="nav-item ml-3 btn-group-vertical"> <a class="nav-link" href="site/login.html">登录</a> </li> <li class="nav-item ml-3 btn-group-vertical dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/> </a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <a class="dropdown-item text-center" href="site/profile.html">个人主页</a> <a class="dropdown-item text-center" href="site/setting.html">账号设置</a> <a class="dropdown-item text-center" href="site/login.html">退出登录</a> <div class="dropdown-divider"></div> <span class="dropdown-item text-center text-secondary">nowcoder</span> </div> </li> </ul> <!-- 搜索 --> <form class="form-inline my-2 my-lg-0" action="site/search.html"> <input class="form-control mr-sm-2" type="search" aria-label="Search" /> <button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button> </form> </div> </nav> </div> </header> <!-- 内容 --> <div class="main"> <div class="container"> <div class="position-relative"> <!-- 筛选条件 --> <ul class="nav nav-tabs mb-3"> <li class="nav-item"> <a class="nav-link active" href="#">最新</a> </li> <li class="nav-item"> <a class="nav-link" href="#">最热</a> </li> </ul> <button type="button" class="btn btn-primary btn-sm position-absolute rt-0" data-toggle="modal" data-target="#publishModal">我要发布</button> </div> <!-- 弹出框 --> <div class="modal fade" id="publishModal" tabindex="-1" role="dialog" aria-labelledby="publishModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。