SpringBoot1.x RestfulCRUD

文章源码

添加资源

将所有的静态资源都添加到 src/main/resources/static 文件夹下,所有的模版资源都添加到 src/main/resources/templates 文件夹下。

创建数据库表,并编写对应实体类。

use web_restful_crud;

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for department
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`id` int(11) primary key NOT NULL AUTO_INCREMENT,
`departmentName` varchar(255) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; use web_restful_crud; SET FOREIGN_KEY_CHECKS=0; -- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) primary key NOT NULL AUTO_INCREMENT,
`lastName` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`gender` int(2) DEFAULT NULL,
`birth` date DEFAULT NULL,
`d_id` int(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
public class Department {
private Integer id;
private String departmentName;
// setter getter toString
} public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender; // 1 male, 0 female
private Date birth;
private Department department;
// setter getter toString
}

默认访问首页

可以使用 WebMvcConfigurerAdapter 可以来扩展 SpringMVC 的功能,可以不用自己实现一个 ViewController。

src/main/java/cn/parzulpan/config/CustomMvcConfig.java

/**
* @Author : parzulpan
* @Time : 2020-12
* @Desc : 自动以配置类,扩展 SpringMVC
*/ @Configuration
public class CustomMvcConfig extends WebMvcConfigurerAdapter { @Override
public void addViewControllers(ViewControllerRegistry registry) {
// 浏览器发送 /parzulpan 请求来到自定义 404 页面
registry.addViewController("/parzulpan").setViewName("404");
} // 将组件注册在容器,所有的 WebMvcConfigurerAdapter 组件都会一起起作用
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
}
};
return adapter;
}
}

国际化

国际化之前添加 Thymeleaf 支持。

<html lang="en">

<link href="asserts/css/bootstrap.min.css" rel="stylesheet">

改为:

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<link href="asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">

这样做的好处是,当通过 server.context-path=/crud 更改项目路径时,静态文件可以自动匹配。


之前使用国际化的步骤:

  • 编写国际化资源文件
  • 使用 ResourceBundleMessageSource 管理国际化资源文件
  • 在页面使用 fmt:message 取出国际化内容

SpringBoot 使用国际化的步骤:

  • 编写国际化配置文件

  • SpringBoot 自动配置好了管理国际化资源文件的组件 MessageSourceAutoConfiguration,它会根据浏览器语言设置的信息切换国际化,即默认的就是根据请求头带来的区域信息获取 Locale 进行国际化

  • 如果想点击链接切换国际化,可以自定义 LocaleResolver(获取区域信息对象)

    /**
    * @Author : parzulpan
    * @Time : 2020-12
    * @Desc : 自定义区域信息解析器
    */ public class CustomLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
    // 获取请求中的语言参数
    String language = request.getParameter("locale");
    Locale locale = Locale.getDefault(); //如果没有就使用默认的
    // 如果请求的链接携带了国际化参数
    if (!StringUtils.isEmpty(language)){
    // zh_CN
    String[] split = language.split("_");
    // 国家,地区
    locale = new Locale(split[0], split[1]);
    }
    return locale; } @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { }
    }
  • 然后在自定义配置类将自定义区域信息解析器添加到容器中

    // 自定义区域信息解析器添加到容器中
    @Bean
    public LocaleResolver localResolver() {
    return new CustomLocaleResolver();
    }

登陆

开发期间模板引擎页面修改以后需要实时生效的步骤:

  • 禁用模板引擎的缓存 spring.thymeleaf.cache=false
  • 页面修改完成以后 Ctrl+F9,重新编译

使用拦截器进行登陆检查

  • 自定义登录拦截器

    /**
    * @Author : parzulpan
    * @Time : 2020-12
    * @Desc : 登录拦截器
    */ public class LoginHandleInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    Object user = request.getSession().getAttribute("loginUser");
    if (user == null) {
    // 未登录,提示信息,并返回登录页面
    request.setAttribute("msg", "没有权限!请先登录!");
    request.getRequestDispatcher("/index").forward(request, response);
    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 { }
    }
  • 注册拦截器到自动配置类

    // 将组件注册在容器,所有的 WebMvcConfigurerAdapter 组件都会一起起作用
    @Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
    WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
    // 注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    // SpringBoot 已经做好了静态资源映射
    registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**")
    .excludePathPatterns("/", "/index", "/index.html", "/user/login");
    }
    };
    return adapter;
    }

Thymeleaf 公共页面元素抽取

比如顶部栏和侧边栏都是公共页面,可以抽取出来。

  • 抽取公共片段

    <div th:fragment="copy">
    &copy; 2011 The Good Thymes Virtual Grocery
    </div>
  • 引入公共片段

    <!--
    ~{templatename::selector}:模板名::选择器
    ~{templatename::fragmentname}:模板名::片段名
    -->
    <div th:insert="~{footer :: copy}"></div>
  • 使用三种不同的引入公共片段的 th属性,引入公共片段后的效果

    • th:insert 将公共片段整个插入到声明引入的元素中

      <div>
      <footer>
      &copy; 2011 The Good Thymes Virtual Grocery
      </footer>
      </div>
    • th:replace 将声明引入的元素替换为公共片段

      <footer>
      &copy; 2011 The Good Thymes Virtual Grocery
      </footer>
    • th:include 将被引入的片段的内容包含进这个标签中

      <div>
      &copy; 2011 The Good Thymes Virtual Grocery
      </div>

RestfulCRUD 分析

URI 格式 /资源名称/资源标识

HTTP 请求方式区分对资源 CRUD 操作

普通CRUD(uri来区分操作) RestfulCRUD
查询 getEmp emp & GET
添加 addEmp?xxx emp & POST
修改 updateEmp?id=1 emp/{id} & PUT
删除 deleteEmp?id=1 emp/{id} & DELETE

员工列表

  • 查询所有员工

    • 请求URI emps
    • 请求方式 GET
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao; @Autowired
DepartmentDao departmentDao; /**
* 查询所有员工,返回列表页面
*/
@GetMapping("/emps")
public String list(Model model) {
Collection<Employee> employees = employeeDao.getAll();
model.addAttribute("emps", employees); // 结果放到请求域中
return "emp/list"; // Thymeleaf 会自动拼串,classpath:/templates/emp/list.html
}
}

员工添加

  • 来到员工添加页面

    • 请求URI emp
    • 请求方式 GET
  • 员工添加
    • 请求URI emp
    • 请求方式 POST
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao; @Autowired
DepartmentDao departmentDao; /**
* 来到员工添加页面
*/
@GetMapping("/emp")
public String toAddPage(Model model) {
// 查询所有部门,在页面显示
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts", departments);
return "emp/add";
} /**
* 员工添加,SpringMVC 会自动进行参数绑定
*/
@PostMapping("/emp")
public String addEmp(Employee employee) {
employeeDao.save(employee);
return "redirect:/emps";
}
}

员工修改

  • 来到员工修改页面

    • 请求URI emp/{id}
    • 请求方式 GET
  • 员工修改
    • 请求URI emp
    • 请求方式 PUT
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao; @Autowired
DepartmentDao departmentDao; /**
* 来到修改页面,查出当前员工,在页面回显
*/
@GetMapping("/emp/{id}")
public String toEditPage(@PathVariable("id") Integer id, Model model) {
Employee employee = employeeDao.get(id);
model.addAttribute("emp", employee);
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts", departments);
return "emp/add"; // add.html 是一个修改和添加二合一的页面
} /**
* 员工修改,SpringMVC 会自动进行参数绑定
*/
@PutMapping("/emp")
public String updateEmp(Employee employee) {
employeeDao.save(employee);
return "redirect:/emps";
}
}

员工删除

  • 查询所有员工

    • 请求URI emp/{id}
    • 请求方式 DELETE
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao; @Autowired
DepartmentDao departmentDao; /**
* 员工删除
*/
@DeleteMapping("/emp/{id}")
public String deleteEmp(@PathVariable("id") Integer id) {
employeeDao.delete(id);
return "redirect:/emps";
}
}

练习和总结

【SpringBoot1.x】RestfulCRUD的更多相关文章

  1. 【SpringBoot1.x】SpringBoot1.x 任务

    SpringBoot1.x 任务 文章源码 异步任务 在 Java 应用中,绝大多数情况下都是通过同步的方式来实现交互处理的.但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使 ...

  2. 【SpringBoot1.x】SpringBoot1.x 开发热部署和监控管理

    SpringBoot1.x 开发热部署和监控管理 热部署 在开发中我们修改一个 Java 文件后想看到效果不得不重启应用,这导致大量时间花费,我们希望不重启应用的情况下,程序可以自动部署(热部署). ...

  3. 【SpringBoot1.x】SpringBoot1.x 分布式

    SpringBoot1.x 分布式 分布式应用 Zookeeper&Dubbo ZooKeeper 是用于分布式应用程序的高性能协调服务.它在一个简单的界面中公开了常见的服务,例如命名,配置管 ...

  4. 【SpringBoot1.x】SpringBoot1.x 安全

    SpringBoot1.x 安全 文章源码 环境搭建 SpringSecurity 是针对 Spring 项目的安全框架,也是 SpringBoot 底层安全模块默认的技术选型.他可以实现强大的 we ...

  5. 【SpringBoot1.x】SpringBoot1.x 检索

    SpringBoot1.x 检索 文章源码 概念 Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本.数字.地理空间.结构化和非结构化数据.Elasticse ...

  6. 【SpringBoot1.x】SpringBoot1.x 消息

    SpringBoot1.x 消息 文章源码 概述 大多应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦能力. 消息服务有两个重要概念,即消息代理(message broker)和目的地(des ...

  7. 【SpringBoot1.x】SpringBoot1.x 缓存

    SpringBoot1.x 缓存 文章源码 JSR107 Java Caching 定义了 5 个核心接口,分别为: CachingProvider 定义了创建.配置.获取.管理和控制多个 Cache ...

  8. 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter

    SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...

  9. 【SpringBoot1.x】SpringBoot1.x 数据访问

    SpringBoot1.x 数据访问 简介 对于数据访问层,无论是 SQL 还是 NOSQL,Spring Boot 默认采用整合 Spring Data 的方式进行统一处理,添加大量自动配置,屏蔽了 ...

随机推荐

  1. 20分钟带你掌握JavaScript Promise和 Async/Await

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.freecodecamp.org/news/learn-promise-a ...

  2. 关于C++的异常抛出

    在接触 throw 之前,我们只知道可以通过函数的返回值来获取和定位错误,比如通过 return 来层层返回是一种方法,但如果牵扯到多层函数调用,那么通过 return 来返回错误显得过于拖沓,这时就 ...

  3. 前端js部署

    1 执行命令 cnpm run build 2.2 提取dist静态资源 将静态资源放置后端static下   /static文件是django后端的部署文件夹 3 Nginx写入配置文件 写入etc ...

  4. java web简单的增删改查

    1.主要的文件,运行结果,运行界面,数据库创建的表等图片. 所要创建的文件和要导入的包: 主页面: 显示界面: 数据库的信息: 删除.查找.修改就不一 一列出来,自己可以运行看看.哈哈 2.接下来我将 ...

  5. MySQL 5.7.29安装配置

    一.环境准备(关闭防火墙) 1.清除已安装数据库 [root@mysql01 ~]# rpm -qa | grep mariadb mariadb-libs-5.5.35-3.el7.x86_64 [ ...

  6. java 系统属性设置

    一.语法: java -Dproperty=value 二.注意事项: value如果有空格,需用使用双引号如:java -Dfoo="some string" 三.常见使用地方: ...

  7. vue第十一单元(内置组件)

    第十一单元(内置组件) #课程目标 熟练掌握component组件的用法 熟练使用keep-alive组件 #知识点 #1.component组件 component是vue的一个内置组件,作用是:配 ...

  8. Mysql技术内幕之InnoDB锁探究

    自7月份换工作以来,期间一直在学习MySQL的相关知识,听了一些视频课,但是一直好奇那些讲师的知识是从哪里学习的.于是想着从书籍中找答案.毕竟一直 看视频也不是办法,不能形成自己的知识.于是想着看书汲 ...

  9. MES系统介绍

    为什么要引入MES系统? 随着ERP在企业应用的深入,ERP系统逐渐显示出其局限性.当ERP下达的工单到生产现场后,产品制造是以产线 "工单"或"批次"(Bat ...

  10. JVM笔记【1】-- 运行时数据区

    目录 (一)java内存区域管理 1.1 程序计数器 1.2 虚拟机栈 1.3 本地方法栈 1.4 java堆 1.5 方法区 1.5.1 运行时常量池 (二)直接内存 (一)java内存区域管理 C ...