流程:

创建项目,勾选基本的几个开发工具还有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. 10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压

    最终结果哈夫曼树,如图所示: 直接上代码: public class HuffmanCode { public static void main(String[] args) { //获取哈夫曼树并显 ...

  2. jvm调优神器——arthas

    在上一篇<jvm调优的几种场景>中介绍了几种常见的jvm方面调优的场景,用的都是jdk自带的小工具,比如jps.jmap.jstack等.用这些自带的工具排查问题时最大的痛点就是过程比较麻 ...

  3. springboot——重定向解决刷新浏览器造成表单重复提交的问题(超详细)

    原因:造成表单重复提交的原因是当我们刷新浏览器的时候,浏览器会发送上一次提交的请求.由于上一次提交的请求方式为post,刷新浏览器就会重新发送这个post请求,造成表单重复提交. 解决办法: 将请求当 ...

  4. mybatis学习——使用注解开发

    前言: 一个语句既可以通过 XML 定义,也可以通过注解定义.不过,由于 Java 注解的一些限制以及某些 MyBatis 映射的复杂性,要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XM ...

  5. mybatis之模糊查询

    1.编写接口 List<User> getUserLike(String value); 2.编写映射文件 <select id="getUserLike" re ...

  6. android小技巧之点击两次退出活动

    通常在主活动中可以设置连击退出程序,下面通过代码来实现这一功能: @Override//按两次back键退出public boolean onKeyDown(int keyCode, KeyEvent ...

  7. 【NX二次开发】根据视图名称旋转视图,在布局中替换视图uc6464

    uc6464("布局名","旧视图名","新视图名");输入布局名.旧视图名.新视图名.如果布局名为空则更新当前布局.如果旧视图名为空,则工 ...

  8. Python 机器学习实战 —— 监督学习(下)

    前言 近年来AI人工智能成为社会发展趋势,在IT行业引起一波热潮,有关机器学习.深度学习.神经网络等文章多不胜数.从智能家居.自动驾驶.无人机.智能机器人到人造卫星.安防军备,无论是国家级军事设备还是 ...

  9. Vue(11)组件化的基本使用

    前言 有时候有一组html结构的代码,并且这个上面可能还绑定了事件.然后这段代码可能有多个地方都被使用到了,如果都是拷贝来拷贝去,很多代码都是重复的,包括事件部分的代码都是重复的.那么这时候我们就可以 ...

  10. 19、lnmp_mysql、nfs组件分离

    19.1.LNMP一体机的数据库分离成独立的数据库: 1.根据以上学习过的方法在db01服务器上安装独立的mysql数据库软件: 2.在web01服务器上导出原先的数据库: [root@web01 t ...