关于自己的一些知识:目前,我是一名Skillbox学生,参加了“ Java开发人员”课程。我绝不谈广告。他于2019年5月开始学习Java,之后他自己单独学习了HTML,CSS和JS。实际上,这促使我写这篇文章时意识到前端如何与后端一起工作,并且对PUT请求缺乏了解。在我“ google”任何地方的Rest API都是通过POST和GET请求实现的,有时是使用DELETE实现的,没有前端的示例。首先,我想传达的是与我将REST API和前端一起实现的方式一样,以便能够理解。但是这篇文章不仅适合我本人,也适合Spring技术的有经验的用户,因为在评论中,我希望看到老同志的正当教导。毕竟,我将根据我的经验描述我的决定(请阅读经验不足的内容)。我遇到了理解Spring的问题,特别是对PUT请求的理解,即更改数据库中元素的数据。我还将描述POST和GET请求。通常,标准CRUD(如果我输入错了,则正确)。还有一点前端,也就是说,在那里,一个请求被发送到服务器并处理了响应。我用了:我还想保留前端部分在培训项目中的功能,我实现了PUT和DELETE查询。可以在GitHub上查看整个项目。一个小技巧:使用maven创建项目时,Java版本跳至第五个,要在pom.xml中修复此问题,我们编写以下代码,其中数字为版本。开放生活黑客<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
弹簧连接
首先,在pom.xml中,我们将Spring boot作为父级连接,这是因为依赖关系的进一步连接不会因版本而冲突:<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
</parent>
现在,我们连接Spring Web负责启动应用程序:<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
我们创建并运行该应用程序
您需要在正确的目录src / main / java / main中开始编写应用程序,是的,没错,我还没有找到解释性的解释,我想我会慢慢发现的。并立即布置应用程序的整个结构。
我所做的第一件事是创建Main.java类以运行带有注释的应用程序@SpringBootApplication
:@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
而且您已经可以单击运行,甚至我的服务器都将启动!
在端口8080上启动。您可以转到该地址http://localhost:8080/
,我们将看到错误404,因为还没有页面。公平地说,您需要实现一个前端。您需要在pom.xml中包括依赖关系以模板化HTML。<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
首先,请访问src / main / resources / templates目录中的index.html起始页。这里有这样简单的标记<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ToDo List</title>
<script src="/js/jquery-3.4.0.min.js"></script>
<script src="/js/main.js"></script>
<link rel="stylesheet" type="text/css" href="/css/styles.css">
</head>
<body>
<div id="todo-form">
<form>
<label> :
</label>
<input id="todo-form-name" type="text" name="name" value="">
<label>:
</label>
<input id="todo-form-description" type="text" name="description" value="">
<label> :
</label>
<input id="todo-form-date" type="date" name="date" value="">
<hr>
</form>
</div>
<h1> </h1>
<button id="show-add-todo-list"> </button>
<br><br>
<div id="todo-list">
</div>
</body>
</html>
我们还在src / main / resources / static / css目录中编写样式,创建styles.css查看样式* {
font-family: Arial, serif;
}
#todo-form {
display: none;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: #88888878;
}
#todo-form form {
background-color: white;
border: 1px solid #333;
width: 300px;
padding: 20px;
}
#todo-form h2 {
margin-top: 0;
}
#todo-form label {
display: block;
}
#todo-form form > * {
margin-bottom: 5px;
}
h4 {
margin-bottom: 0;
}
您可以尝试启动该应用程序然后继续http://localhost:8080/
,您可以欣赏起始页,尽管到目前为止没有任何操作。当然,src / main / resources / static / js目录中的带有jQuery插件的js,我再次预约,在培训项目中已经有jQuery和main.js的一部分。所有关于Java和Spring同一集线器,所以链接的完整代码的js认为将是足够的:链接到jQuery的3.4.0.min.js
链接到main.js。以下将特别注意GET和PUT的请求。无论是从服务器端还是从前端。现在,您可以尝试启动项目,并确保前端也可以正常工作并执行操作(添加按钮将启动表单)。数据库交互
下一步是与数据库进行交互的实体,为此,我们连接了Spring数据jpa依赖项:<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
然后在src / main / java / main / model目录中创建一个POJO类Todo附加注释@Entity
。我们声明字段,我将拥有:ID,名称,描述,日期。单独注意setDate()
,我只是在String的输入处执行了该操作,然后转换为java.util.Date,甚至使用atStartOfDay().atZone(ZoneId.of("UTC")
,我也注意了date字段的注释:package main.model;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
@Entity
public class Todo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String description;
@Temporal(TemporalType.DATE)
private Date date;
public void setDate(String date) {
this.date = Date.from(LocalDate.parse(date).atStartOfDay().atZone(ZoneId.of("UTC")).toInstant());
}
}
在pom.xml中添加依赖项以建立与MySQL的连接:<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
在src / main / resources目录中,创建application.properties并写入数据以连接到数据库:spring.datasource.url=jdbc:mysql://localhost:3306/todolist?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=none
现在让我们继续创建存储库。在src / main / java / main / model目录中,创建带有注释的TodoRepository接口,@Repository
并继承CrudRepository <Todo,Integer>。抒情离题-据我了解,这是数据库和控制器之间的垫圈,Spring很有用,您无需创建套接字,无需担心与数据库交互,它可以为您做所有事情。package main.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TodoRepository extends CrudRepository<Todo, Integer> {
}
实际上,与数据库的通信将通过此存储库进行。现在是时候创建一个控制器,在该控制器中处理来自前端的请求,与数据库的交互以及前端响应。在src / main / java / main / controller目录中,创建带有注释的TodoController类@RestController
,声明TodoRepository变量并通过构造函数进行初始化。让我们从POST请求开始。我们创建add()方法来接受Todo并返回int(id),并用批注标记@PostMapping(“/todo-list/”)
和添加路径。我们获取存储库,save()
并将请求随附的Todo对象保存到方法中的数据库中。只是魔术。@PostMapping("/todo-list/")
public int add(Todo todo) {
Todo newTodo = todoRepository.save(todo);
return newTodo.getId();
}
通常,类似于GET和DELETE,但使用id并在ResponseEntity shell中返回Todo。还要注意,该方法的参数get()
带有注释,下面有更详细的说明。然后生成一个响应ResponseEntity.ok(todoOptional.get());
,即代码200,或者如果此id找不到该响应,则返回主体为null的代码404。@GetMapping("/todo-list/{id}")
public ResponseEntity<Todo> get(@PathVariable int id){
Optional<Todo> todoOptional = todoRepository.findById(id);
if(todoOptional.isEmpty()){
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
return ResponseEntity.ok(todoOptional.get());
}
前端方面发生了什么?使用GET示例:单击todo =>列表中的链接,我们拉出id todo =>形成一个请求(请注意,id本身未传递给该方法。get()方法中的id是从(value =“ / todo-list / {id} “)为此,我们需要@PathVariable
在方法参数中添加一个注释)=>答案以Todo对象的形式出现=>前端会执行其认为合适的操作,在这种情况下,Todo具有说明和日期。代码段main.js,GET实现$(document).on('click', '.todo-link', function(){
var link = $(this);
var todoId = link.data('id');
$.ajax({
method: "GET",
url: '/todo-list/' + todoId,
success: function(response)
{
if($('.todo-div > span').is('#' + todoId)){
return;
}
link.parent().append(codeDataTodo(response, todoId));
},
error: function(response)
{
if(response.status == 404) {
alert(' !');
}
}
});
return false;
});
让我们创建另一个控制器,该控制器将立即在开始页面上显示待办事项列表。我们还使用存储库并获取Todo列表,然后将todoList神奇地传递给前端:@Controller
public class DefaultController {
@Autowired
TodoRepository todoRepository;
@RequestMapping("/")
public String index(Model model){
Iterable<Todo> todoIterable = todoRepository.findAll();
ArrayList<Todo> todoList = new ArrayList<>();
for(Todo todo : todoIterable){
todoList.add(todo);
}
model.addAttribute("todoList", todoList);
return "index";
}
}
在index.html中进行了此类更正后,动态加载todoList发生了:<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div id="todo-list">
<div class="todo-div" th:each="todo : ${todoList}" th:attr="id=${todo.id}">
<a href="#" class="todo-link" th:attr="data-id=${todo.id}" th:text="${todo.name}"></a>
<br>
</div>
</div>
提出要求
在TodoController中,我们创建一个方法put()
,该方法@PutMapping
在输入Map <String,String>上带有注释,@RequestParam
并带有注释和int,该int从值提取,位于封装在ResponseEntity中的Todo的输出。而且该存储库没有update()方法,因此所有操作如下:Todo是通过todoRepository通过id =>从新数据库中提取的Todo =>分配了新参数Todo =>它通过该存储库保存在数据库中=>发送前端响应@PutMapping(value = "todo-list/{id}")
public ResponseEntity<Todo> put(@RequestParam Map<String, String> mapParam, @PathVariable int id){
Optional<Todo> todoOptional = todoRepository.findById(id);
if(todoOptional.isEmpty()){
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
todoOptional.get().setName(mapParam.get("name"));
todoOptional.get().setDescription(mapParam.get("description"));
todoOptional.get().setDate(mapParam.get("date"));
todoRepository.save(todoOptional.get());
return ResponseEntity.ok(todoOptional.get());
}
此时,在前端:单击“更改”按钮=>从元素中收集Todo数据=>编辑表单以更改大小写(重命名表单名称,并将按钮替换为输入值Todo data)=>表单已打开=>驱动更改数据=>单击以下形式的“更改”按钮=>数据收集=>生成了一个PUT请求(路径,数据)=>接收到来自修改的Todo对象的响应,但是具有相同的id =>前端执行了它想要的操作,在这种情况下是数据替换去做。代码段main.js,PUT的实现
$(document).on('click', '#show-update-todo-list', function(){
var buttonUpdate = $(this);
var todoId = buttonUpdate.data('id');
var todoName = buttonUpdate.data('name');
var todoDescription = buttonUpdate.data('description');
var todoDate = buttonUpdate.data('date');
todoFormNameAndButton(' ', '', 'update-todo');
todoInputValue(todoName, todoDescription, todoDate);
$('#todo-form').css('display', 'flex');
$('#update-todo').click(function() {
var data = $('#todo-form form').serialize();
$.ajax({
method: "PUT",
url: '/todo-list/' + todoId,
data: data,
success: function(response) {
$('#todo-form').css('display', 'none');
response.date = response.date.slice(0,10);
$('.todo-div#' + todoId + ' > a').text(response.name);
$('.todo-div#' + todoId +' > span').replaceWith(codeDataTodo(response, todoId));
}
});
return false;
});
});
您可以在github上更详细地了解该项目。它是为初学者而设计的,但是我想听听经验丰富的用户的建设性批评。如果您在注释中解释为什么在请求PUT时为什么Map <String,String>出现在控制器端,为什么我不能在那里提交Todo,也很酷。资源: