流程:

创建项目,勾选基本的几个开发工具还有webstarter

再创建包(service,control,config,dao,pojo)

再前往https://www.webjars.org/,选择bootstrap和jquery的依赖导入

注意:在导入jquery和bootstrap中如何导入我们的对应文件

<script type="text/javascript" src="webjars/jquery/3.6.0/jquery.js"></script>
<script type="text/javascript" src="webjars/bootstrap/5.0.1/js/bootstrap.js"></script>
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/5.0.1/css/bootstrap.min.css">

导入thmeleaf依赖,并配置(不导入这个依赖,在templates文件中加载的html模板是找不到的)

尝试写一个index.html

<body class="text-center">
<form class="form-sigin">
<img class="mb-4 img-thumbnail" src="https://exploit-typora.oss-cn-shenzhen.aliyuncs.com/img/IMG_20210410_100617.png" alt="" width="200" height="200">
<h1 class="h3 mb-3 font-weight-normal">please login in</h1>
<label for="user-name" class="sr-only">username</label>
<!--注意:一定要用label标签把input标签包含起来,不然就导致input标签不居中-->
<label>
<input id="user-name" type="text" name="username" class="form-control" required="" autofocus="">
</label>
<label for="password" class="sr-only">password</label>
<label>
<input id="password" type="password" name="password" class="form-control" required="" autofocus="">
</label>
<br>
<div class="check-box mb-3">
<label>
<input type="checkbox" value="remember-me">remember
</label>
</div>
<button type="submit" class="btn btn-lg btn-primary btn-block">login</button>
<p class="mt-5 mb-3 text-muted"> 2020-2034</p>
<p class="btn btn-sm">中文</p>
<a class="btn btn-sm">English</a>
</form>
</body>

写一个配置类,把“/”和"/index"和"/index.html"都对应到index主页

@Configuration
public class ViewResolver implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}

添加thmeleaf命名空间,和form的提交url

<html lang="en" xmlns:th=http://www.thymeleaf.org
xmlns:sec=http://www.thymeleaf.org/extras/spring-security
xmlns:shiro=http://www.pollix.at/thymeleaf/shiro > <!--注意:url在thmeleaf中需要用@开头-->
<form class="form-sigin" th:action="@{/test}" method="post">

测试编写对应的登录控制器

@PostMapping("/test")
@ResponseBody
public String test(@RequestParam("username")String username,
@RequestParam("password")String password){
System.out.println(username+password);
return "OK!!";
}

添加功能:判断用户密码是否正确

  • 控制器:
@PostMapping("login")
public String login(@RequestParam("username")String username,
@RequestParam("password")String password,
Model model,
HttpSession session){
//判断用户密码是否正确,成功了,登录状态码为200且在session中会有用户名,否则登录状态码为200
if (username.equals("admin") && password.equals("123456")){
session.setAttribute("loginStatus",200);
session.setAttribute("username",username);
//成功了直接重定向到list去获取用户数据
return "redirect:list";
}else{
session.setAttribute("loginStatus",400);
//失败了加上session状态码,然后继续返回到index页面
return "index";
}
} @GetMapping("list")
public String list(){
return "list";
}
  • 模板:
<!--只有当if里面的条件成立了才会显示这段语句-->
<div th:if="${session.loginStatus==400}">
<div class="alert alert-danger" role="alert">用户名或密码错误!!!</div>
</div>

添加功能:当没有登录的时候进入其他页面会自动跳转到登录页面

这是一个拦截器功能,需要创建一个HandleInterceptor类,还有一个配置类

  • HandleInterceptor类
//注意这个配置类必须要放置到IOC容器中去
@Component
public class LoginHandleInterceptor implements HandlerInterceptor {
//把三个方法全部重写,主要是第一个方法,后面的方法可删去
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object loginStatus = request.getSession().getAttribute("loginStatus");
if (loginStatus==null){
//未登录状态
response.sendRedirect("/");
return false;
}else{
if ((Integer) loginStatus == 400){
//登录失败状态
response.sendRedirect("/");
return false;
}else{
//登录成功
return true;
}
}
} @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 MyConfig implements WebMvcConfigurer { //视图控制
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
} @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandleInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/","/index","/index.html","/login");
}
}

首页到此为止

下面开始处理list员工列表

先把对应的url想好

  • list-input:(GET) /input (不带参数)

  • input-list: (POST) /saveEmployee(带了name,gender,email,departmentId参数)

  • list-delete: (GET)/delete (带一个对应的employee的id的参数)

  • list-update:(GET) /update(带一个对应的employee的id的参数)

  • update-list:(POST) /updateEmployee(带了email和departmentId的参数)

然后就是直接实现即可

注意:

关键是更新怎么实现:

list界面到input界面-带入对应的员工id的参数,在控制器处加入updateStatus状态码和对应的这个employee的对象,到了input界面则根据updateStatus状态码判断进入update部分用对应的这个employee对象进行手动回显,并且将name和gender设为disabled(隐藏提交id,name,gender),然后在控制器处new一个新对象,把这个新对象用save方法加入到employeeDao中去

get方法怎么携带参数?

两种方式:

  • /employee/1001

    <a th:href="@{/employee/{id}(id=1001)}"></a>
    或者
    <a th:href="@{/employee/{id}(id=${employee.id})}"></a>
  • /employee?id=1001

    <a th:href="@{/employee(id=1001)}"></a>
    或者
    <a th:href="@{/employee(id=${employee.id})}"></a>

怎么让表单不能被使用但又可以提交?

两种方式:

  • readonly:只读模式

    在最后面加上readonly属性即可,但是只有input才有效,seletor没用

    <input class="form-control" type="text" placeholder="Readonly input here…" readonly>
    
    
  • disabled:禁用模式

    在最后面加上disabled属性即可,但是会把要提交的信息也给禁用了,需要另外隐藏提交相关信息

    <input class="form-control" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

展示最终thmeleaf页面为:

  • list界面
<body class="text-center">
<div class="contaniner">
<div class="row">
<div class="col-md-4">
<h4>【[[${session.username}]]】 sir</h4>
</div>
</div>
<div class="row">
<div class="col-md-4">
<a th:href="@{/input}"><button class="bnt btn-primary">Add Employee</button></a>
</div>
</div>
<div class="row">
<div class="col-md-offset-2 col-md-10">
<table class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>name</th>
<th>gender</th>
<th>email</th>
<th>departmentId</th>
<th>departmentName</th>
<th>handle</th>
</tr>
</thead>
<tbody>
<tr th:each="employee:${employees}">
<th th:text="${employee.getId()}"></th>
<th th:text="${employee.getLastName()}"></th>
<div th:if="${employee.getGender()==1}">
<th>男</th>
</div>
<div th:if="${employee.getGender()==0}">
<th>女</th>
</div>
<th th:text="${employee.getEmail()}"></th>
<th th:text="${employee.getDepartment().getDepartmentId()}"></th>
<th th:text="${employee.getDepartment().getDepartmentName()}"></th>
<th> <a th:href="@{/update(id=${employee.getId()})}"><button class="btn btn-danger">alter</button></a>
<!--这个携带参数是用?携带参数,还有一种是比如:/employee/1001携带参数-->
<!---->
<a th:href="@{/delete(id=${employee.getId()})}"><button class="btn btn-primary">delete</button></a>
</th>
</tr>
</tbody>
</table>
</div>
</div>
</div> </body>
  • input界面
<body>
<div class="container"> <!--添加员工界面-->
<div th:if="${updateStatus==null}">
<form class="form-horizontal" th:action="@{/saveEmployee}" method="post">
<h3>添加员工</h3>
<!--name-->
<div class="form-group">
<label for="name" class="col-sm-4 control-label"><strong>Name</strong></label>
<div class="col-sm-4">
<input type="text" name="name" class="form-control" id="name" placeholder="name">
</div>
</div>
<!--gender-->
<div class="form-group">
<label class="col-sm-4 "><strong>Gender</strong></label>
<div class="col-sm-4">
<select name="gender" class="form-control">
<option value="1">男</option>
<option value="0">女</option>
</select>
</div>
</div> <!--email-->
<div class="form-group">
<label for="email" class="col-sm-4 control-label"><strong>Email</strong></label>
<div class="col-sm-4">
<input type="email" name="email" class="form-control" id="email" placeholder="email">
</div>
</div>
<!--department-->
`<div class="form-group">
<label class="col-sm-4 control-label"><strong>Department</strong></label>
<div class="col-sm-4">
<select class="form-control" name="departmentId">
<div th:each="department:${departments}">
<option th:text="${department.getDepartmentId()}"></option>
</div>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success btn-sm">CONFIRM ADD</button>
</div>
</div>
</form>
</div> <!--修改员工界面-->
<div th:if="${updateStatus=='update'}">
<form class="form-horizontal" th:action="@{/updateEmployee}" method="post">
<h3>修改员工</h3>
<input type="hidden" th:value="${updateEmployee.getId()}" name="employeeId">
<input type="hidden" th:value="${updateEmployee.getLastName()}" name="name">
<input type="hidden" th:value="${updateEmployee.getGender()}" name="gender">
<!--name-->
<div class="form-group" readonly>
<label for="updateName" class="col-sm-4 control-label"><strong>Name</strong></label>
<div class="col-sm-4">
<input th:value="${updateEmployee.getLastName()}" type="text" name="name" class="form-control" id="updateName" placeholder="name" disabled>
</div>
</div>
<!--gender-->
<div class="form-group">
<label class="col-sm-4 "><strong>Gender</strong></label>
<div class="col-sm-4">
<div th:if="${updateEmployee.getGender()==1}">
<select th:value="${updateEmployee.getGender()}" name="gender" class="form-control" disabled>
<option value="1">男</option>
<option value="0">女</option>
</select>
</div>
<div th:if="${updateEmployee.getGender()==0}">
<select id="disableInput" th:value="${updateEmployee.getGender()}" name="gender" class="form-control" disabled>
<option value="0">女</option>
<option value="1">男</option>
</select>
</div>
</div>
</div>
<!--email-->
<div class="form-group">
<label for="updateEmail" class="col-sm-4 control-label"><strong>Email</strong></label>
<div class="col-sm-4">
<input th:value="${updateEmployee.getEmail()}" type="email" name="email" class="form-control" id="updateEmail" placeholder="email">
</div>
</div>
<!--department-->
<div class="form-group">
<label class="col-sm-4 control-label"><strong>Department<span style="color: #c0392b;font-weight: 700">(NOW:[[${updateEmployee.getDepartment().getDepartmentId()+"."+updateEmployee.getDepartment().getDepartmentName()}]])</span></strong></label>
<div class="col-sm-4">
<select class="form-control" name="departmentId">
<div th:each="department:${departments}">
<option th:text="${department.getDepartmentId()}"></option>
</div>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success btn-sm">CONFIRM UPDATE</button>
</div>
</div>
</form>
</div>
</div>
</body>

springboot-4-CRUD开发实战的更多相关文章

  1. 小D课堂【SpringBoot】接口Http协议开发实战

    ---恢复内容开始--- ====================2.SpringBoot接口Http协议开发实战 ============================= 1.SpringBoot ...

  2. SpringBoot微服务电商项目开发实战 --- Redis缓存雪崩、缓存穿透、缓存击穿防范

    最近已经推出了好几篇SpringBoot+Dubbo+Redis+Kafka实现电商的文章,今天再次回到分布式微服务项目中来,在开始写今天的系列五文章之前,我先回顾下前面的内容. 系列(一):主要说了 ...

  3. SpringBoot微服务电商项目开发实战 --- api接口安全算法、AOP切面及防SQL注入实现

    上一篇主要讲了整个项目的子模块及第三方依赖的版本号统一管理维护,数据库对接及缓存(Redis)接入,今天我来说说过滤器配置及拦截设置.接口安全处理.AOP切面实现等.作为电商项目,不仅要求考虑高并发带 ...

  4. SpringBoot微服务电商项目开发实战 --- 模块版本号统一管理及Redis集成实现

    上一篇文章总结了基于SpringBoot实现分布式微服务下的统一配置.分环境部署配置.以及服务端模块的分离(每一个提供者就是一个独立的微服务).微服务落地.Dubbo整合及提供者.消费者的配置实现.本 ...

  5. 图书-技术-SpringBoot:《Spring Boot 企业级应用开发实战》

    ylbtech-图书-技术-SpringBoot:<Spring Boot 企业级应用开发实战> Spring Boot 企业级应用开发实战,全书围绕如何整合以 Spring Boot 为 ...

  6. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-10.Springboot2.x用户登录拦截器开发实战

    笔记 10.Springboot2.x用户登录拦截器开发实战     简介:实战开发用户登录拦截器拦截器 LoginInterceptor                  1.实现接口 LoginI ...

  7. SpringBoot:Web开发

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 , 基于atguigu 1.5.x 视频优化 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处 ...

  8. [原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

    原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) 前言:上一篇文章讲述了一些实现DAL的理论,本 ...

  9. 《精通Spring 4.X企业应用开发实战》读书笔记1-1(IoC容器和Bean)

    很长一段时间关注在Java Web开发的方向上,提及到Jave Web开发就绕不开Spring全家桶系列,使用面向百度,谷歌的编程方法能够完成大部分的工作.但是这种不系统的了解总觉得自己的知识有所欠缺 ...

  10. 11. SpringBoot 之CRUD实例

    SpringBoot静态页路径,可直接通过URL访问的: /META-INF/resources /resources /static /public 而    5. /template 只和模板引擎 ...

随机推荐

  1. NVIDIA空中导航SDK改造5G通信

    NVIDIA空中导航SDK改造5G通信 Transforming Next-Generation Wireless with 5T for 5G and the NVIDIA Aerial SDK N ...

  2. day05对象和类

    day06作业: 第一题:分析以下需求,并用代码实现 手机类Phone 属性: 品牌brand 价格price 行为: 打电话call() 发短信sendMessage() 玩游戏playGame() ...

  3. 导出 Excel 模板自动生成规则,避免用户来回修改

    一句话总结 Excel 导出.导入时,根据注解自动添加单元格验证规则,避免用户因填写错误的枚举字段而反复修改 Excel 需求背景 对于 Java Web 项目,总是不可避免的出现 Excel 导入. ...

  4. NEXTCLOUD 常见错误

    HTTP请求头"Strict-Transport-Security"没有配置为至少"15552000"秒出于增强安全性考虑推荐按照安全提示中的说明启用HSTS ...

  5. Android开发问题之Installation failed due to invalid URI!

    真机调试遇到以下问题: [2017-07-20 13:43:53 - VCL02PANEL] Installation failed due to invalid URI![2017-07-20 13 ...

  6. 图解 Redis | 不多说了,这就是 RDB 快照

    大家好,我是小林. 虽说 Redis 是内存数据库. 但是它为数据的持久化提供了两个技术,分别是「 AOF 日志和 RDB 快照」. 这两种技术都会用各用一个日志文件来记录信息,但是记录的内容是不同的 ...

  7. 【LeetCode每日一题 Day 5】5. 最长回文子串

    大家好,我是编程熊,今天是LeetCode每日一题的第五天,一起学习LeetCode第五题<最长回文子串>. 题意 给你一个字符串 s,找到 s 中最长的回文子串. 示例 输入:s = & ...

  8. 仅使用JsonUtility && File类实现Json数据读写

    using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using S ...

  9. 16、如何将安装在chrome上的插件(扩展程序)打包成".crx"文件

    1.打开扩展程序: 2.打开开发者模式并选择要打包的插件: 3.打包扩展程序: (1) (2) (3)

  10. 关于easyswoole实现websocket聊天室的步骤解析

    在去年,我们公司内部实现了一个聊天室系统,实现了一个即时在线聊天室功能,可以进行群组,私聊,发图片,文字,语音等功能,那么,这个聊天室是怎么实现的呢?后端又是怎么实现的呢? 后端框架 在后端框架上,我 ...