SpringBoot+MyBatis+Thymeleaf最简洁最完整中小型web前后端开发模板

  • 最近整理了一篇基于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

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值