restful风格的增删改查

注意

  • 如果静态资源放到了静态资源文件夹下却无法访问,请检查一下是不是在自定义的配置类上加了@EnableWebMvc注解
  • templete文件夹不是静态资源的文件夹,默认是无法访问的,所以要添加视图映射
package cn.xxxxxx.hellospringbootweb.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyMvcConfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");registry.addViewController("/index").setViewName("login");registry.addViewController("/index.html").setViewName("login");}
}

 i18n国际化

  1. 编写国际化配置文件,抽取页面需要显示的国际化消息

    创建i18n文件夹存放配置文件,文件名格式为基础名(login)+语言代码(zh)+国家代码(CN)

  2. 在配置文件中添加国际化文件的位置和基础名,如果配置文件中没有配置基础名,就在类路径下找基础名为message的配置文件

    spring.messages.basename=i18n.login
    1. 点击切换语言    修改页面,点击连接携带语言参数
    <a class="btn btn-sm" href="?l=zh_CN">中文</a>
    <a class="btn btn-sm" href="?l=en_US">English</a>

实现登陆功能

1,提供登陆的Controller

@Controller
public class UserController {@PostMapping("/user/login")public String login(@RequestParam String username, @RequestParam String password, HttpSession session, Model model) {if (!StringUtils.isEmpty(username) && "123456".equals(password)) {//登录成功,把用户信息方法哦session中,防止表单重复提交,重定向到后台页面session.setAttribute("loginUser", username);return "redirect:/main.html";}//登录失败,返回到登录页面model.addAttribute("msg", "用户名或密码错误!");return "login";}
}

2,修改表单的提交地址,输入框添加name值与参数名称相对应

        <form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post"><img class="mb-4" src="asserts/img/bootstrap-solid.svg" alt="" width="72" height="72"><h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1><label class="sr-only">Username</label><input type="text" name="username" class="form-control" th:placeholder="#{login.username}" placeholder="Username" autofocus=""><label class="sr-only">Password</label><input type="password" name="password" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required=""><div class="checkbox mb-3"><label><input type="checkbox" value="remember-me"> [[#{login.remember}]]</label></div><button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button><p class="mt-5 mb-3 text-muted">© 2017-2018</p><a class="btn btn-sm" href="?l=zh_CN">中文</a><a class="btn btn-sm" href="?l=en_US">English</a></form>

3,由于登陆失败是转发,所以得修改静态资源的请求路径,在其中添加模版引擎

<link  href="asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">

4,添加登陆页面的显示,将msg传回主页面

<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!--msg存在才显示该p标签-->
<p th:text="${msg}" th:if="${not #strings.isEmpty(msg)}" style="color: red"></p>

修改页面使其立即生效

在配置文件里面添加如下的命令,在页面修改完成之后,按快捷键ctrl+f9,重新编译

# 禁用缓存
spring.thymeleaf.cache=false

拦截器进行登陆检查

1,实现拦截器

package cn.xxxxxx.hellospringbootweb.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class LoginHandlerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object loginUser = request.getSession().getAttribute("loginUser");if (loginUser == null) {//未登录,拦截,并转发到登录页面request.setAttribute("msg", "您还没有登录,请先登录!");request.getRequestDispatcher("/index").forward(request, response);return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

2,注册拦截器

package cn.clboy.hellospringbootweb.config;import cn.clboy.hellospringbootweb.interceptor.LoginHandlerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyMvcConfig implements WebMvcConfigurer {//定义不拦截路径private static final String[] excludePaths = {"/", "/index", "/index.html", "/user/login", "/asserts/**"};@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");registry.addViewController("/index").setViewName("login");registry.addViewController("/index.html").setViewName("login");registry.addViewController("/main.html").setViewName("dashboard");}@Beanpublic LocaleResolver localeResolver() {return new MyLocaleResolver();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {//添加不拦截的路径,SpringBoot已经做好了静态资源映射,所以我们不用管registry.addInterceptor(new LoginHandlerInterceptor()).excludePathPatterns(excludePaths);}
}

注意:在spring2.0+的版本中,只要用户自定义了拦截器,则静态资源会被拦截。但是在spring1.0+的版本中,是不会拦截静态资源的。因此我们需要将静态资源排除到拦截器的拦截路径之外

案例,实现员工的增删改查

实验功能请求URI请求方式
查询所有员工empsGET
查询某个员工(来到修改页面)emp/1GET
来到添加页面empGET
添加员工empPOST
来到修改页面(查出员工进行信息回显)emp/1GET
修改员工empPUT
删除员工emp/1DELETE
  1. 为了页面结构清晰,在template文件夹下新建emp文件夹,将list.html移动到emp文件夹下

  2. 将dao层和实体层java代码复制到项目中daoentities

  3. 添加员工controller,实现查询员工列表的方法

    @Controller
    public class EmpController {@Autowiredprivate EmployeeDao employeeDao;@GetMapping("/emps")public String emps(Model model) {Collection<Employee> empList = employeeDao.getAll();model.addAttribute("emps", empList);return "emp/list";}}
  4. 修改后台页面,更改左侧的侧边栏,并修改请求路径
    <li class="nav-item"><a class="nav-link" th:href="@{/emps}"><svg .....>......</svg>员工列表</a>
    </li>

thymeleaf公共页面元素抽取(参考官方文档)

  • ~{templatename::selector}:模板名::选择器
  • ~{templatename::fragmentname}:模板名::片段名
/*公共代码片段*/
<footer th:fragment="copy">&copy; 2011 The Good Thymes Virtual Grocery
</footer>/*引用代码片段*/
<div th:insert="~{footer :: copy}"></di/*(〜{...}包围是完全可选的,所以上⾯的代码 将等价于:*/
<div th:insert="footer :: copy"></di

三种引入公共片段的th属性:

  • th:insert:将公共片段整个插入到声明引入的元素中
  • th:replace:将声明引入的元素替换为公共片段
  • th:include:将被引入的片段的内容包含进这个标签中

后台页面的抽取

1,将后台主页中的顶部导航栏作为片段,在list中引入

        <nav th:fragment="topbar" class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0"><a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Company name</a><input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"><ul class="navbar-nav px-3"><li class="nav-item text-nowrap"><a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a></li></ul></nav>

2,list.html

<body><div th:replace="dashboard::topbar"></div>......

3,使用选择器的方式抽取左侧边栏的代码,就是我们将不同html文件的公共部分抽取出来,作为一个模版,其余需要的html文件只需要引入即可使用。比如现在我们将名称为sidebar的模版放在dashboard.html里面,而在list.html里面进行复用。

<!--dashboard.html-->
<div class="container-fluid"><div class="row"><nav id="sidebar" class="col-md-2 d-none d-md-block bg-light sidebar" ......
<!--list.html-->
<div class="container-fluid"><div class="row"><div th:replace="dashboard::#sidebar"></div>......

4,显示员工数据,添加增删改按钮

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2><button class="btn btn-sm btn-success">添加员工</button></h2><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>员工号</th><th>姓名</th><th>邮箱</th><th>性别</th><th>部门</th><th>生日</th><th>操作</th></tr></thead><tbody><tr th:each="emp:${emps}"><td th:text="${emp.id}"></td><td th:text="${emp.lastName}"></td><td th:text="${emp.email}"></td><td th:text="${emp.gender}==1?'男':'女'"></td><td th:text="${emp.department.departmentName}"></td><td th:text="${#dates.format(emp.birth,'yyyy-MM-dd')}"></td><td><button class="btn btn-sm btn-primary">修改</button><button class="btn btn-sm btn-danger">删除</button></td></tr></tbody></table></div></main>

5,员工添加页面 add.html

......
<body>
<div th:replace="commons/topbar::topbar"></div><div class="container-fluid"><div class="row"><div th:replace="commons/sidebar::#sidebar(currentURI='emps')"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form><div class="form-group"><label>LastName</label><input name="lastName" type="text" class="form-control" placeholder="zhangsan"></div><div class="form-group"><label>Email</label><input  name="email" type="email" class="form-control" placeholder="zhangsan@atguigu.com"></div><div class="form-group"><label>Gender</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="gender" value="1"><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="gender" value="0"><label class="form-check-label">女</label></div></div><div class="form-group"><label>department</label><select name="department.id" class="form-control"><option th:each="dept:${departments}" th:text="${dept.departmentName}" th:value="${dept.id}"></option></select></div><div class="form-group"><label>Birth</label><input name="birth" type="text" class="form-control" placeholder="zhangsan"></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
......

6,点击链接,跳转到添加页面

<a href="/emp" th:href="@{/emp}" class="btn btn-sm btn-success">添加员工</a>

7,EmpController添加映射方法

    @Autowiredprivate DepartmentDao departmentDao;@GetMapping("/emp")public String toAddPage(Model model) {//准备部门下拉框数据Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("departments",departments);return "emp/add";}

8, 修改页面遍历添加下拉选项

<select class="form-control"><option th:each="dept:${departments}" th:text="${dept.departmentName}"></option>
</select>

9,表单提交,添加员工

<form th:action="@{/emp}" method="post">
    @PostMapping("/emp")public String add(Employee employee) {System.out.println(employee);//模拟添加到数据库employeeDao.save(employee);//添加成功重定向到列表页面return "redirect:/emps";}

10,日期格式的修改

表单提交的格式必须是yyyy/MM/dd的格式,可以在配置文件中修改格式

spring.mvc.date-format=yyyy-MM-dd

员工修改

  1. 点击按钮跳转到编辑页面
     <a th:href="@{/emp/}+${emp.id}" class="btn btn-sm btn-primary">修改</a>
  2. 添加编辑页面,将表单的提交方式设置为post方式,提供_method参数
    <body>
    <div th:replace="commons/topbar::topbar"></div><div class="container-fluid"><div class="row"><div th:replace="commons/sidebar::#sidebar(currentURI='emps')"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form th:action="@{/emp}" method="post"><!--员工id--><input type="hidden" name="id" th:value="${emp.id}"><!--http请求方式--><input type="hidden" name="_method" value="put"><div class="form-group"><label>LastName</label><input name="lastName" th:value="${emp.lastName}" type="text" class="form-control" placeholder="zhangsan"></div><div class="form-group"><label>Email</label><input  name="email" th:value="${emp.email}" type="email" class="form-control" placeholder="zhangsan@atguigu.com"></div><div class="form-group"><label>Gender</label><br/><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="gender" value="1" th:checked="${emp.gender==1}"><label class="form-check-label">男</label></div><div class="form-check form-check-inline"><input class="form-check-input" type="radio" name="gender" value="0" th:checked="${emp.gender==0}"><label class="form-check-label">女</label></div></div><div class="form-group"><label>department</label><select name="department.id" class="form-control"><option th:each="dept:${departments}" th:value="${dept.id}" th:selected="${dept.id}==${emp.department.id}" th:text="${dept.departmentName}"></option></select></div><div class="form-group"><label>Birth</label><input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${#dates.format(emp.birth,'yyyy-MM-dd')}"></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
    </div>......
  3. controller转发到编辑页面,回显员工信息
        @GetMapping("/emp/{id}")public String toEditPage(@PathVariable Integer id, Model model) {Employee employee = employeeDao.get(id);//准备部门下拉框数据Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("emp", employee).addAttribute("departments", departments);return "emp/edit";}
  4. 提交表单修改员工的信息
        @PutMapping("/emp")public String update(Employee employee) {employeeDao.save(employee);return "redirect:/emps";}

员工删除

  1. 点击删除提交发出delete请求
        @DeleteMapping("/emp/{id}")public String delete(@PathVariable String id){employeeDao.delete(id);return "redirect:/emps";}
  2. 如果提示不支持POST请求,在确保代码无误的情况下查看是否配置启动HiddenHttpMethodFilter
  3. 这个好像是2.0版本以后修改的
    spring.mvc.hiddenmethod.filter.enabled=true
  4. 如果删除不掉,请修改EmployeeDao,把String转为Integer类型

        public void delete(String id) {employees.remove(Integer.parseInt(id));}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

历史上最有影响力的10款开源项目

开源是大趋势&#xff0c;开源软件也在越来越多的出现在日常电脑桌面上&#xff0c;如Firefox浏览器、Ubuntu操作系统等。人们选择开源软件的原因&#xff0c;主要有低成本、安全无病毒侵害、更加透明和开放等。按照大多数的开源协议如GPL&#xff0c;开源软件允许自由分发。在…

SpringBoot默认的错误处理机制

错误处理机制&#xff1a; 访问一个不存在的页面时&#xff0c;或者程序抛出异常时 默认效果 浏览器返回一个错误的页面&#xff0c;注意查看浏览器发送请求的请求头可以使用专业的软件比如postman分析返回的json数据 springboot错误处理的自动配置信息 主要给日容器中注册…

GitHub政府用户破万:开源成重塑政府新手段

据GitHub官方博客介绍&#xff0c;目前GitHub上的各地政府用户数量已经达到1万个&#xff01; 2009年&#xff0c;纽约参议院正式入驻GitHub公开部分技术资料与文档&#xff0c;成为GitHub上的第一个政府组织。随后&#xff0c;美国华盛顿特区、迈阿密、芝加哥、纽约&#xff…

云OS:Linux在桌面打翻身仗的机会?

不可否认&#xff0c;Chrome OS取得了惊人的增长。Chromebook自发行以来&#xff0c;迅速席卷全球&#xff0c;常年位居最畅销笔记本榜首。这款基于Linux的笔记本在合适时间提供了合适的解决方案。很多情况下&#xff0c;云不仅仅是一个可选项&#xff0c;而是一个最优选项。Li…

Docker容器基本使用

Dcoker Docker是一个开源的应用容器引擎&#xff0c;是一个轻量级别的容器技术Dcoker支持将软件编译成一个镜像&#xff1b;然后在镜像中对各种软件做好配置&#xff0c;再将镜像发布出去&#xff0c;供别人使用运行中的镜像称为容器&#xff0c;容器的启动是非常快速的核心概…

为什么35岁的C++依然能主导编程世界

早在1979年&#xff0c;Bjarne Stroustrup设计了C编程语言&#xff0c;并且C很快成为了无处不在的通用系统编程语言。现在尽管有Java、Javascript、Python、Go&#xff0c;甚至是苹果的Swift和它竞争&#xff0c;但C依然处于主导编程世界的地位。 今天在Morgan Stanley的科技访…

SpringBoot整合JPA

添加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId&…

为什么说选择正确的编程语言很重要,以及如何正确的选择

几个月前&#xff0c;一个同事问我&#xff0c;应该如何选择编程语言&#xff0c;或者有没有什么固定的选择模式&#xff0c;当时我便打算写点什么。上周在硅谷开会&#xff0c;这我是第一次跟“hack3rs”的创业狂以及技术狂们打交道。我学会了很多前所未闻的脏话&#xff0c;也…

细数开源历史上的十个重大事件

开放源码&#xff08;开源&#xff09;的精神在于使用者可以使用、复制、散布、研究和改进软件。这可以追溯到20世纪60年代&#xff0c;至今已有半个世纪了。虽然下面所列举的不都是专门的开源产品&#xff0c;但还是在开源发展的进程中有着巨大的影响。开放源码&#xff08;开…

深度卷积神经网络CNNs的多GPU并行框架及其应用

摘要&#xff1a;本文是腾讯深度学习系列文章之一&#xff0c;主要聚焦于腾讯深度学习平台&#xff08;Tencent Deep Learning Platform&#xff09;中深度卷积神经网络Deep CNNs的多GPU模型并行和数据并行框架。 【编者按】深度卷积神经网络有着广泛的应用场景&#xff0c;本…

线程安全和对应的核心概念

线程安全 线程安全的概念&#xff1a;当多个线程访问某一个类&#xff08;对象和方法&#xff09;时&#xff0c;这个类始终都能表现出正确的行为&#xff0c;那么这个类&#xff08;对象或者方法&#xff09;就是线程安全的synchronized&#xff1a;可以在任意对象及方法上加…

JDK Unsafe类的使用与CAS原子特性

JDK Unsafe类的使用与CAS原子特性 Java.util.concurrent.atomic包&#xff0c;其中包含了大量使用到Unsafe这个类Java不能直接访问操作系统的底层&#xff0c;而是通过本地方法来访问。 Unsafe类提供了硬件级别的原子操作&#xff0c;主要提供了以下功能 内存操作字段的定位和…

写软件不是造汽车

写软件和做其他事情是不一样的。当我们制造别的东西的时候——像汽车、玩具、椅子、画作、甚至包括数字产品如平面图片和3D模型——我们做出来的成品就是最终的结果。而开发软件则不是&#xff0c;我们做出来的产品永远不可能有最终的结果——我们需要向计算机解释如何根据任意…

网站盈利的10种方式

如果你有自己的网站&#xff0c;而且已经有了不少的流量&#xff0c;你肯定会开始考虑如何通过这个网站来挣一些钱。 在这篇文章中&#xff0c;我会向大家介绍网站最常见的10种盈利方式。 1.按点击付费广告 在网站上展示一个按点击付费的广告横幅是最简单的盈利方式&#xff…

Redis数据的类型

Redis一共分为五种基本数据类型&#xff1a;String、Hash、List、Set、Zset. string 内部编码有三种&#xff0c;raw&#xff0c;embstr&#xff0c;int String 是二进制的。可以存储序列化对象&#xff0c;图片&#xff0c;字符串&#xff0c;数值等 set和get方法 &#x…

Redis高级命令与特性以及单点模式的介绍

高级命令 keys * 返回满足条件的所有key&#xff0c;可以模糊匹配exists 是否存在指定的keypersist 取消过期时间select 选择数据库 &#xff08;0-15&#xff0c;总共16个数据库&#xff09;move key index 将当前数据库的 key 移动到给定的数据库 db 当中randomkey 随机返回…

同为程序员 为什么我的工资最低

我看着工资单上每一个开发团队成员的薪水&#xff0c;慢慢地我不能保持淡定了。 而当我看到我的工资排名是倒数的时候——靠近最后一名——我不由得倒抽一口冷气。就像圣诞故事中的那个可爱的小男孩Ralphie &#xff0c;想买气枪却被忽悠会有危险一样&#xff0c;我也不断忽悠…

redis.conf配置文件详解

基本配置 daemonize no #是否以后台进程启动databases 16 #创建database的数量(默认选中的是database 0)save 900 1 #刷新快照到硬盘中&#xff0c;必须满足两者要求才会触发&#xff0c;即900秒之后至少1个关键字发生变化save 300 10 #必须是300秒之后至少10个关键字发生变…

用Unix的设计思想来应对多变的需求

摘要&#xff1a;无论是Unix设计&#xff0c;还是面向对象设计&#xff0c;还是别的什么如SOA&#xff0c;ECB&#xff0c;消息&#xff0c;事件&#xff0c;MVC&#xff0c;网络七层模型&#xff0c;数据库设计&#xff0c;等等&#xff0c;他们都在干三件事——解耦&#xff…

有关编程的12个猜想

摘要&#xff1a;编程世界的将来如何目前仍难预料&#xff0c;但可以肯定的一点是技术一直在加速发展。本文搜罗出12个独特的编程视角猜想&#xff0c;一起来看看有哪些猜想在不久的将来就能变为现实。 编程世界的将来如何目前仍难预料&#xff0c;但可以肯定的一点是技术一直…