- 最近整理了一篇基于SpringBoot前后端完整的开发框架,这个框架的优点是基本无配置,开发简单对于前端基础薄弱的甚至无前端基础的,只要通过简单的学习也能够开发出一个完整的前后端系统出来,本着开源的目的介绍完本篇后会将我整理一个星期做的基于SpringBoot+MyBatis+Thymeleaf的一个小型的系统模型附上链接,有需要的朋友可以自行下载,有问题可以留言~~
- 本篇重点介绍整合SpringBoot+MyBatis+Thymeleaf,附带知识点包括(mybatis自带代码生成器、拦截器配置、简单分页、Https配置、用户令牌Token设计)等等,是不是迫不及待了呢?
项目结构截图如下:
MyBatis自带代码生成器配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
<classPathEntry location="E:\办公软件\mysql-connector-java-5.1.6-bin.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="false"/>
</commentGenerator>
<!--数据库连接驱动类,URL,用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1/weaveplat" userId="root" password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成(实体)模型的包名和位置-->
<javaModelGenerator targetPackage="com.sy.weaveplat.entity" targetProject="src">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成XML映射文件的包名和位置-->
<sqlMapGenerator targetPackage="resources.mapper" targetProject="src">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成DAO接口的包名和位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.sy.weaveplat.mapper" targetProject="src">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
<table tableName="student" domainObjectName="Student" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
在pom.xml的配置
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
SpringBoot整合MyBatis
在pom.xml引入:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
```这个starter自动集成了SpringBoot对mybatis的配置,无需在写额外的mybatis的xml配置文件,可以看到这个项目没有一个xml配置文件,然后在application.yml配置mybatis如下:
mybatis:
mapper-locations: classpath:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.example.springboottest1.entity # 注意:对应实体类的路径
这样SpringBoot就完美的整合了MyBatis,是不是很简洁~~
基于session的简单拦截器配置
首先需要自己写一个拦截器类实现HandlerInterceptor接口,如下:
@Component
public class LoginInterceptor implements HandlerInterceptor {
//这个方法是在访问接口之前执行的,我们只需要在这里写验证登陆状态的业务逻辑,就可以在用户调用指定接口之前验证登陆状态了
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//每一个项目对于登陆的实现逻辑都有所区别,我这里使用最简单的Session提取User来验证登陆。
HttpSession session = request.getSession();
//这里的User是登陆时放入session的
User user = (User) session.getAttribute("user");
//如果session中没有user,表示没登陆
if(user == null){
//这个方法返回false表示忽略当前请求,如果一个用户调用了需要登陆才能使用的接口,如果他没有登陆这里会直接忽略
//当然你可以利用response给用户返回一些提示信息,告诉他没登陆
response.sendRedirect("/login/loginHtml");
return false;
}else{
return true; //如果session里有user,表示该用户已经登陆,方行,用户即可继续调用自己需要的接口
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
然后写一个全局配置类注册这个接口:
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
//这个方法是用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//registry.addResourceHandler("/download/**").addResourceLocations("file:E:/AuthDeployTools/download/");
//registry.addResourceHandler("/templates/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX+"/templates/");
//registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX+"/static/");
//super.addResourceHandlers(registry);
}
//这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
//addPathPatterns("/**")表示拦截所有的请求
//excludePathPatterns("/login","/register")表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**","/register","/static/**","/templates/**");
//super.aadInterceptors(registry); //较新Srping Boot的版本中这里可以直接去掉,否则会报错
}
}
在登录的controller设置session拦截器
//使用session存储user用来配置拦截器
request.getSession().setAttribute("user", user);
这样只要用户没有登录成功都会被拦截到登录界面~~
使用SpringBoot自带的前端模板引擎Thymeleaf和mysql的Limit完成分页配置
前端html界面分页代码
<!--分页-->
<div>当前第<span th:text="${localp}"></span>页</div>
<span><a th:if="${localp}>0" th:href="@{/user/selectByPage(page=${localp} - 1)}">上一页</a></span>
<span><a th:if="${localp}<${totalpages}-1" th:href="@{/user/selectByPage(page=${localp}+1)}">下一页</a></span>
后端分页代码
users = iUserService.selectUserByCondition(null, null, null, null);
/*object = new JSONObject();
object.put("result",users);
object.put("message","恭喜查找成功");
return object;*/
int totleSzie = users.size(); //总记录数int curPage = 1; //当前页面数
int totlePage = 0; //总页数
if (totleSzie % Const.PAGESIZE == 0) {
totlePage = totleSzie / Const.PAGESIZE;
} else {
totlePage = totleSzie / Const.PAGESIZE + 1;
}
model.addAttribute("localp", 1);
model.addAttribute("totalpages", totlePage);
model.addAttribute("users", users);
return "user";
Https配置
使用jdk自带的keystore生成一个证书
在application.yml配置如下:
server:
port: 8443
#port:8080
ssl:
key-store: E:\IDEAMyBatisProject\创建springboot项目\testObject1\tomcat.keystore
key-store-password: XXXXX
key-store-type: JKS
key-alias: tomcat
配置8080跳转
@Configuration
public class ConnectorConfig {
//@Value("${server.port.http}")
private int serverPortHttp = 8080;
@Value("${server.port}")
private int serverPortHttps;
@Bean
public ServletWebServerFactory servletWebServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection securityCollection = new SecurityCollection();
securityCollection.addPattern("/*");
securityConstraint.addCollection(securityCollection);
context.addConstraint(securityConstraint);
}
};
factory.addAdditionalTomcatConnectors(redirectConnector());
return factory;
}
private Connector redirectConnector() {
Connector connector = new Connector(Http11NioProtocol.class.getName());
connector.setScheme("http");
connector.setPort(serverPortHttp);
connector.setSecure(false);
connector.setRedirectPort(serverPortHttps);
return connector;
}
}
这样https配置就完成了~~如下图
启动项目在L浏览器输入:
由于是自己制作的证书未经谷歌等浏览器认证所以会警告不安全,当然可以向证书申请机构申请付费的证书
用户Token设置
用于验证该用户访问后端api接口的权限
public class Token {
public User user; //用户登录的个人信息
public Equipment equipment; //用户登录设备信息
public Login login; //该用户的登录信息,用于维护更新
public String userToken; //用户令牌
public String createDate; //该Token的创建时间
/**
* 无参构造函数
*/
public Token(){
super();
}
/**
* 有参构造函数
* @param user
* @param equipment
*/
public Token(User user,Equipment equipment,Login login){
this.userToken = UUIDUtil.getUuidReplace();
this.createDate = DateUtils.GetCurrentDate();
this.user = user;
this.equipment = equipment;
this.login = login;
}
/**
* get方法获取用户
* @return
*/
public User getUser(){
return user;
}
/**
* get方法获取设备
* @return
*/
public Equipment getEquipment(){
return equipment;
}
/**
* 返回该用户的登录信息
* @return
*/
public Login getLogin(){return login;}
/**
* get方法获取用户token
* @return
*/
public String getUserToken(){
return userToken;
}
}
TokenManager用于管理所有用户的Token,如下:
public class TokenManager {
private static TokenManager tokenManager = null;
private List<Token> tokenList;
//存放心跳正常在线设备
//通过检测设备api接口,如果半小时内访问过的设备就放在正常设备接口(注意重复添加)
//相当于加了一个黑白名单
private List<Token> normalToken;
//存放心跳异常在线设备(即用户未退出设备,但是设备已经不工作了出现故障了)
private List<Token> abnormalToken;
/**
* 无参构造函数
*/
public TokenManager(){
super();
tokenList = new ArrayList<Token>();
}
/**
* 获取单列实例
* @return
*/
public static TokenManager getInstance(){
if(tokenManager == null){
tokenManager = new TokenManager();
}
return tokenManager;
}
/**
* 添加token
* @param token
* @return
*/
public boolean addToken(Token token){
boolean bool = false;
if(token != null && tokenList != null){
if(tokenList.size() != 0){
if(!tokenList.contains(token)){
tokenList.add(token);
}
}else{
tokenList.add(token);
}
}
return bool;
}
/**
* 获取Token
* @param userToken
* @return
*/
public Token getToken(String userToken){
Token token = null;
for(int i = 0; i < tokenList.size(); i++){
token = tokenList.get(i);
if(userToken.equals(token.getUserToken())){
return token;
}
}
return token;
}
/**
* 根据设备码来获取Token(用户检测该设备是否在线)
* @param equipmentNum
* @return
*/
public Token getTokenByEuipmentNum(String equipmentNum){
Token token = null;
for(int i = 0; i < tokenList.size(); i++){
token = tokenList.get(i);
if(equipmentNum.equals(token.getEquipment().getEquipmentNum())){
return token;
}
}
return token;
}
/**
* 移除Token
* @param userToken
* @return
*/
public boolean removeToken(String userToken){
boolean bool = false;
for(int i = 0; i < tokenList.size(); i++){
if(userToken.equals(tokenList.get(i).getUserToken())){
tokenList.remove(i);
bool = true;
}
}
return bool;
}
/**
* 避免同一用户重复登录
* @param user
*/
public void removeOldUserToken(User user){
List<Token> old = new ArrayList<Token>();
User user1 = null;
for(int i = 0; i < tokenList.size(); i++){
user1 = tokenList.get(i).getUser();
if(user1.getUserName().equals(user.getUserName())){
old.add(tokenList.get(i));
}
}
if(old.size() != 0){
tokenList.removeAll(old);
}
}
系统界面截图如下:
错误跳转
用户界面
该界面的主要功能如下:
1、用户列表展示
2、用户的添加、修改及删除
3、多条件组合搜索及模糊查询
4、简单分页
用户界面前端代码,使用的是Thymeleaf模板,原型即页面,无任何.js和.css文件
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户管理</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- <script language="javascript" type="text/javascript">
function page(curPage) {
$("#curpage").val(curPage);
$("#form").submit();
}
</script>-->
</head>
<body>
<fieldset>
<legend>查询条件</legend>
<form id="form" action="/user/selectUser" method="post">
<table>
<tr>
<td>
<select name="num">
<option value="1">根据用户id查询</option>
<option value="2">根据用户名查询</option>
<option value="3">根据用户创建时间查询</option>
<option value="4">根据用户角色查询</option>
</select>
</td>
<td>
<input type="text" name="keyword"/>
</td>
<td>
<input type="submit" value="提交"/>
</td>
</tr>
<tr>
<td>用户编号</td>
<td>用户姓名</td>
<td>用户电话</td>
<td>用户描述</td>
<!-- <td>用户签名</td>-->
<td>用户创建时间</td>
<td>用户对应的角色</td>
<td><a href="/user/addUser">新增</a></td>
</tr>
<tr th:each="user,memberStat:${users}">
<td th:text="${memberStat.index + 1}"></td>
<td th:text="${user.userName}"></td>
<td th:text="${user.userPhone}"></td>
<td th:text="${user.userDescribe}"></td>
<!-- <td th:text="${user.userSignature}"></td>-->
<td th:text="${user.createDate}"></td>
<td th:text="${user.role.roleName}"></td>
<td>
<a th:href="@{/user/deleteUser(id=${user.id})}">删除</a>
<a th:href="@{/user/updateHtml(id=${user.id})}">修改</a>
</td>
</tr>
</table>
<!--分页-->
<div>当前第<span th:text="${localp}"></span>页</div>
<span><a th:if="${localp}>0" th:href="@{/user/selectByPage(page=${localp} - 1)}">上一页</a></span>
<span><a th:if="${localp}<${totalpages}-1" th:href="@{/user/selectByPage(page=${localp}+1)}">下一页</a></span>
</form>
</fieldset>
</body>
</html>
本篇到此结束,欢饮评论及留言~~项目下载地址
https://download.csdn.net/my