CRUD using Spring MVC 4.0 RESTful Web Services and AngularJS

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。

国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html
内部邀请码:C8E245J (不写邀请码,没有现金送)
国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为中国PE第一股,市值超1000亿元。 

------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

原文: http://www.tuicool.com/articles/MneeU3f

Based on the requests from many readers, I am now presenting an article on how to make CRUD operations using Spring MVC 4.0 RESTFul web services and AngularJS. I had already written few articles on Spring MVC 4.0 RESTFul Web Services in case you are new to this.

For the sake of best understanding, I came up with a small task manager AngularJS application powered by Spring MVC 4.0 RESTFul Web Services. With this application, you can list all existing tasks, create a new task, mark completion of an existing task and archive completed tasks. I had tried to keep it very simple as this is not for real time use but for the best understanding of the concept.

DEMO  DOWNLOAD

Prerequisites

-- MySql Server

-- Eclipse J2EE

-- Tomcat Server v7.0

1. Let us start by creating task table in MySql Server.

Execute the below commands in MySql Server. This will create a dedicated database for our application and will create a task_list table with dummy values to start with initially,

use taskmanager;
create table task_list(task_id int not null auto_increment, task_name varchar(100) not null, task_description text,task_priority varchar(20),task_status varchar(20),task_start_time datetime not null,task_end_time datetime not null,task_archived bool default false,primary key(task_id)); insert into task_list values(1,'Gathering Requirement','Requirement Gathering','MEDIUM','ACTIVE',curtime(),curtime() + INTERVAL 3 HOUR,0); insert into task_list values(2,'Application Designing','Application Designing','MEDIUM','ACTIVE',curtime(),curtime() + INTERVAL 2 HOUR,0); insert into task_list values(3,'Implementation','Implementation','MEDIUM','ACTIVE',curtime(),curtime() + INTERVAL 3 HOUR,0); insert into task_list values(4,'Unit Testing','Unit Testing','LOW','ACTIVE',curtime(),curtime() + INTERVAL 4 HOUR,0); insert into task_list values(5,'Maintanence','Maintanence','LOW','ACTIVE',curtime(),curtime() + INTERVAL 5 HOUR,0); select * from task_list;

2.  Download

        -- Spring MVC 4.0 jar files from this maven repository  here

.


        --  Download latest version of jackson json library from  her e

             (1) jackson-annotations-x.x.x.jar

             (2) jackson-core-x.x.x.jar

             (3) jackson-databind-x.x.x.jar

        -- Download mysql java connector library.

3. Create a dynamic web project in eclipse and add the above downloaded jar files to your application WEN-INF\lib folder.

 

4. Now edit web.xml file under WebContent folder to notify the application container about the spring configuration file. Add below code before </web-app>

<servlet>
 <servlet-name>rest</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rest</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>

Note that in the above code,we have named Spring Dispatcher servlet class as "rest" and the url pattern is given as "/*" which means any uri with the root of this web application will call DispatcherServlet. So what's next? DispatcherServlet will look for configuration files following this naming convention -  [servlet-name]-servlet.xml . In this example, I have named dispatcher servlet class as "rest" and hence it will look for file named 'rest-servlet.xml'.


5. Create a file under WEB-INF folder and name it as "rest-servlet.xml". Add below spring configuration code to it,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="  http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd  http://www.springframework.org/schema/mvc  http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <context:component-scan base-package="com.programmingfree.springservice.controller" /> <mvc:annotation-driven /> </beans>
I have already explained component-scan element and mvc:annotation-driven element in my previous article, so I am not going to repeat it here again.

6. Create a Java class and name it "Task.java". This is the model class and it represents the fields of a single task in the database.

package com.programmingfree.springservice.domain;

public class Task {
 
 private int task_id; private String task_name; private String task_description; private String task_priority; private String task_status; public int getTaskId() { return task_id; } public void setTaskId(int taskId) { this.task_id = taskId; } public String getTaskName() { return task_name; } public void setTaskName(String taskName) { this.task_name = taskName; } public String getTaskDescription() { return task_description; } public void setTaskDescription(String taskDescription) { this.task_description = taskDescription; } public String getTaskPriority() { return task_priority; } public void setTaskPriority(String taskPriority) { this.task_priority = taskPriority; } public String getTaskStatus() { return task_status; } public void setTaskStatus(String taskStatus) { this.task_status = taskStatus; } @Override public String toString() { return "Task [task_id=" + task_id + ", task_name=" + task_name + ", task_description=" + task_description + ", task_priority=" + task_priority +",task_status="+task_status+ "]"; } }

7. Create a utility class to handle connections to database. The connection string properties are kept in a configuration file called "db.properties" in the src folder.

package com.programmingfree.springservice.utility;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class DBUtility { private static Connection connection = null;  public static Connection getConnection() {   if (connection != null)    return connection;   else {    try {    Properties prop = new Properties();     InputStream inputStream = DBUtility.class.getClassLoader().getResourceAsStream("/config.properties");     prop.load(inputStream);     String driver = prop.getProperty("driver");     String url = prop.getProperty("url");     String user = prop.getProperty("user");     String password = prop.getProperty("password");     Class.forName(driver);     connection = DriverManager.getConnection(url, user, password);    } catch (ClassNotFoundException e) {     e.printStackTrace();    } catch (SQLException e) {     e.printStackTrace();    } catch (FileNotFoundException e) {     e.printStackTrace();    } catch (IOException e) {     e.printStackTrace();    }    return connection;   }  } }

Properties configuration file should have contents such as this,

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/databasename

user=username

password=xxxxxx

 

8. Create a service class that performs data access operations to get data from database,

package com.programmingfree.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.programmingfree.springservice.domain.*; import com.programmingfree.springservice.utility.DBUtility; public class TaskManagerService { private Connection connection; public TaskManagerService() { connection = DBUtility.getConnection(); } public void addTask(Task task) { try { PreparedStatement preparedStatement = connection .prepareStatement("insert into task_list(task_name,task_description,task_priority,task_status,task_archived,task_start_time,task_end_time) values (?, ?, ?,?,?,?,?)"); System.out.println("Task:"+task.getTaskName()); preparedStatement.setString(1, task.getTaskName()); preparedStatement.setString(2, task.getTaskDescription()); preparedStatement.setString(3, task.getTaskPriority()); preparedStatement.setString(4, task.getTaskStatus()); preparedStatement.setInt(5,0); Date dt = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currentTime = sdf.format(dt); preparedStatement.setString(6,currentTime); preparedStatement.setString(7,currentTime); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void archiveTask(int taskId) { try { PreparedStatement preparedStatement = connection .prepareStatement("update task_list set task_archived=true where task_id=?"); // Parameters start with 1 preparedStatement.setInt(1, taskId); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void updateTask(Task task) throws ParseException { try { PreparedStatement preparedStatement = connection .prepareStatement("update task_list set task_name=?, task_description=?, task_priority=?,task_status=?" + "where task_id=?"); preparedStatement.setString(1, task.getTaskName()); preparedStatement.setString(2, task.getTaskDescription()); preparedStatement.setString(3, task.getTaskPriority()); preparedStatement.setString(4, task.getTaskStatus()); preparedStatement.setInt(4, task.getTaskId()); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public void changeTaskStatus(int taskId,String status) throws ParseException { try { PreparedStatement preparedStatement = connection .prepareStatement("update task_list set task_status=? where task_id=?"); preparedStatement.setString(1,status); preparedStatement.setInt(2, taskId); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } public List<task> getAllTasks() { List<task> tasks = new ArrayList<task>(); try { Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery("select * from task_list where task_archived=0"); while (rs.next()) { Task task = new Task(); task.setTaskId(rs.getInt("task_id")); task.setTaskName(rs.getString("task_name")); task.setTaskDescription(rs.getString("task_description")); task.setTaskPriority(rs.getString("task_priority")); task.setTaskStatus(rs.getString("task_status")); tasks.add(task); } } catch (SQLException e) { e.printStackTrace(); } return tasks; } public Task getTaskById(int taskId) { Task task = new Task(); try { PreparedStatement preparedStatement = connection. prepareStatement("select * from task_list where task_id=?"); preparedStatement.setInt(1, taskId); ResultSet rs = preparedStatement.executeQuery(); if (rs.next()) { task.setTaskId(rs.getInt("task_id")); task.setTaskName(rs.getString("task_name")); task.setTaskDescription(rs.getString("task_description")); task.setTaskPriority(rs.getString("task_priority")); task.setTaskStatus(rs.getString("task_status")); } } catch (SQLException e) { e.printStackTrace(); } return task; } }

9. Create Spring Controller class that maps the incoming request to appropriate methods and returns response in json format. We are going to use @RestController annotation which has @Controller and @Responsebody annotated within itself.

package com.programmingfree.springservice.controller;

import java.text.ParseException;
import java.util.List;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.programmingfree.dao.TaskManagerService; import com.programmingfree.springservice.domain.Task; @RestController public class TaskManagerController { TaskManagerService taskmanagerservice=new TaskManagerService(); @RequestMapping(value="/tasks",method = RequestMethod.GET,headers="Accept=application/json") public List<task> getAllTasks() { List<task> tasks=taskmanagerservice.getAllTasks(); return tasks; } @RequestMapping(value="/tasks/archive/{taskIds}",method = RequestMethod.POST,headers="Accept=application/json") public List<task> archiveAllTasks(@PathVariable int[] taskIds) { for(int i=0;i<taskids .length="" ask="" i="" list="" taskids="" taskmanagerservice.archivetask=""> tasks=taskmanagerservice.getAllTasks(); return tasks; } @RequestMapping(value="/tasks/{taskId}/{taskStatus}",method = RequestMethod.POST,headers="Accept=application/json") public List<task> changeTaskStatus(@PathVariable int taskId,@PathVariable String taskStatus) throws ParseException { taskmanagerservice.changeTaskStatus(taskId,taskStatus); return taskmanagerservice.getAllTasks(); } @RequestMapping(value="/tasks/insert/{taskName}/{taskDesc}/{taskPriority}/{taskStatus}",method = RequestMethod.POST,headers="Accept=application/json") public List<task> addTask(@PathVariable String taskName,@PathVariable String taskDesc,@PathVariable String taskPriority,@PathVariable String taskStatus) throws ParseException { Task task = new Task(); task.setTaskName(taskName); task.setTaskDescription(taskDesc); task.setTaskPriority(taskPriority); task.setTaskStatus(taskStatus); taskmanagerservice.addTask(task); return taskmanagerservice.getAllTasks(); } }

Let us now take a closer look into the methods we have in the Spring Controller class.

-- Initially we use getAllTasks () method to fetch all tasks from database. This will fetch all tasks that are not archived (task_archived = '0').

-- Then we give an option to the user via archiveTasks() method, to archive all completed tasks so that it won't show up on the dashboard. For this purpose, we have a field in task_list table called 'task_archived' with values 0 or 1 marking whether a task is archived or not.

-- An option to update the status of a task from 'ACTIVE' to 'COMPLETED' or vice-versa is provided in the changeStatus() method

-- AddTask() method enables one to add a new task to the database.

10. Let us now create the jsp file that sends requests to the Spring controller to fetch data and to update data in the server,

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html ng-app="taskManagerApp"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>AngularJS Task Manager</title> <script data-require="angular.js@*" data-semver="1.2.13" src="http://code.angularjs.org/1.2.13/angular.js"></script> <script type="text/javascript" src="./js/app.js"></script> </head> <body> <div ng-controller="taskManagerController"> <div id="task-panel" class="fadein fadeout showpanel panel" ng-show="toggle"> <div class="panel-heading"> <i class="panel-title-icon fa fa-tasks"></i> <span class="panel-title">Recent Tasks</span> <div class="panel-heading-controls"> <button ng-click="toggle = !toggle" >Add New Task</button> <button confirmed-click="archiveTasks()" ng-confirm-click="Would you like to archive completed tasks?">Clear completed tasks</button> </div> </div> <div> <div ng-repeat="task in tasks"> <span> {{task.taskPriority}} </span> <div> <input id="{{task.taskId}}" type="checkbox" value="{{task.taskId}}" ng-checked="selection.indexOf(task.taskId) > -1" ng-click="toggleSelection(task.taskId)" /> <label for="{{task.taskId}}"></label> </div> <div ng-if="task.taskStatus=='COMPLETED'"> <a href="#" class="checkedClass"> {{task.taskName}} <span class="action-status">{{task.taskStatus}}</span> </a> </div> <div ng-if="task.taskStatus=='ACTIVE'"> <a href="#" class="uncheckedClass"> {{task.taskName}} <span class="action-status">{{task.taskStatus}}</span> </a> </div> </div> </div> </div> <div id="add-task-panel" ng-hide="toggle"> <div> <span>Add Task</span> <div> <button ng-click="toggle = !toggle">Show All Tasks</button> </div> </div> <div> <div> <table> <tr> <td>Task Name:</td> <td><input type="text" ng-model="taskName"/></td> </tr> <tr> <td>Task Description:</td> <td><input type="text" ng-model="taskDesc"/></td> </tr> <tr> <td>Task Status:</td> <td> <select ng-model="taskStatus" ng-options="status as status for status in statuses"> <option value="">-- Select --</option> </select> </td> </tr> <tr> <td>Task Priority:</td> <td> <select ng-model="taskPriority" ng-options="priority as priority for priority in priorities"> <option value="">-- Select --</option> </select> </td> </tr> <tr> <td><br/><button ng-click="addTask()" class="btn-panel-big">Add New Task</button></td> </tr> </table> </div> </div> </div> </div> </body> </html>

Note that I have not included any styling elements or animations though I have used it in the demonstration to keep the code clean for easy understanding.

11. In the above JSP file, I had referenced a  javascript file called 'app.js' in the head section. Create a file called 'app.js' under WebContent/js folder and copy the below code in it.

var taskManagerModule = angular.module('taskManagerApp', ['ngAnimate']);

taskManagerModule.controller('taskManagerController', function ($scope,$http) { var urlBase="http://localhost:8080/TaskManagerApp"; $scope.toggle=true; $scope.selection = []; $scope.statuses=['ACTIVE','COMPLETED']; $scope.priorities=['HIGH','LOW','MEDIUM']; $http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; //get all tasks and display initially $http.get(urlBase+'/tasks'). success(function(data) { $scope.tasks = data; for(var i=0;i<$scope.tasks.length;i++){ if($scope.tasks[i].taskStatus=='COMPLETED'){ $scope.selection.push($scope.tasks[i].taskId); } } }); //add a new task $scope.addTask = function addTask() { if($scope.taskName=="" || $scope.taskDesc=="" || $scope.taskPriority == "" || $scope.taskStatus == ""){ alert("Insufficient Data! Please provide values for task name, description, priortiy and status"); } else{ $http.post(urlBase + '/tasks/insert/' +$scope.taskName+'/'+$scope.taskDesc+'/'+$scope.taskPriority+'/'+$scope.taskStatus). success(function(data) { alert("Task added"); $scope.tasks = data; $scope.taskName=""; $scope.taskDesc=""; $scope.taskPriority=""; $scope.taskStatus=""; $scope.toggle='!toggle'; }); } }; // toggle selection for a given task by task id $scope.toggleSelection = function toggleSelection(taskId) { var idx = $scope.selection.indexOf(taskId); // is currently selected if (idx > -1) { $http.post(urlBase + '/tasks/' +taskId+'/ACTIVE'). success(function(data) { alert("Task unmarked"); $scope.tasks = data; }); $scope.selection.splice(idx, 1); } // is newly selected else { $http.post(urlBase + '/tasks/' +taskId+'/COMPLETED'). success(function(data) { alert("Task marked completed"); $scope.tasks = data; }); $scope.selection.push(taskId); } }; // Archive Completed Tasks $scope.archiveTasks = function archiveTasks() { $http.post(urlBase + '/tasks/archive/' + $scope.selection). success(function(data) { $scope.tasks = data; alert("Successfully Archived"); }); }; }); //Angularjs Directive for confirm dialog box taskManagerModule.directive('ngConfirmClick', [ function(){ return { link: function (scope, element, attr) { var msg = attr.ngConfirmClick || "Are you sure?"; var clickAction = attr.confirmedClick; element.bind('click',function (event) { if ( window.confirm(msg) ) { scope.$eval(clickAction); } }); } }; }]);

-- AngularJS gets activated with the ng-app directive placed in the html tag.

-- When the browser loads the div element with ng-controller directive 'taskManagerController', the controller module in the above javascript file executes. It makes http call to get all tasks initially and display in the jsp file.

--  When the user checks the check box placed near every task, the task is marked completed and when the user unchecks the check box, the task is again marked active.

-- On clicking 'Clear Completed Tasks' button, archiveTasks() method in the above javascript file is executed and all the tasks that are marked as completed are archived by changing the value of task_archived field in the database to 1. This method makes an http post request to the server to change the task_archived field value of all completed tasks. Note that we are just archiving the tasks but not deleting it, so it will always be there in the database but won't show up in the application.

-- A new task entry is added to the database by making an http post when the user clicks on 'Add task' button.

To understand how this application works, you can see a simple static demonstration using the demo link below. To completely understand how this works from the server side with a database, download the application and run it yourself using the instructions below.

DEMO  DOWNLOAD

Instructions to run the download

1. Download the project using the download link above and unzip it.

2. Follow Step 1 of this article to create a database, table with dummy values. Simply execute the given query.

3. Make sure MySql Service is running.

4. Import the downloaded project in eclipse.

5. Right Click 'index.jsp' and run it in Tomcat Web Server v7.0

6. Note that you need data connection to get angularjs up and running in the project as we have referenced the latest version from angularjs cdn repository directly. You can also download angularjs library and reference it in index.jsp

You must be seeing the following page once you run it from Tomcat Web Server,

Keep yourself subscribed for getting programmingfree articles delivered directly to your inbox once in a month. Thanks for reading!

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
7月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
347 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
7月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
531 0
|
7月前
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
345 0
|
7月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestMapping
@RequestMapping 是 Spring MVC 中用于请求地址映射的注解,可作用于类或方法上。类级别定义控制器父路径,方法级别进一步指定处理逻辑。常用属性包括 value(请求地址)、method(请求类型,如 GET/POST 等,默认 GET)和 produces(返回内容类型)。例如:`@RequestMapping(value = &quot;/test&quot;, produces = &quot;application/json; charset=UTF-8&quot;)`。此外,针对不同请求方式还有简化注解,如 @GetMapping、@PostMapping 等。
298 0
|
7月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RestController
本文主要介绍 Spring Boot 中 MVC 开发常用的几个注解及其使用方式,包括 `@RestController`、`@RequestMapping`、`@PathVariable`、`@RequestParam` 和 `@RequestBody`。其中重点讲解了 `@RestController` 注解的构成与特点:它是 `@Controller` 和 `@ResponseBody` 的结合体,适用于返回 JSON 数据的场景。文章还指出,在需要模板渲染(如 Thymeleaf)而非前后端分离的情况下,应使用 `@Controller` 而非 `@RestController`
229 0
|
3月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
200 0
|
3月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
116 0
|
3月前
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
180 0
|
12月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
161 4
|
7月前
|
XML JSON API
Understanding RESTful API and Web Services: Key Differences and Use Cases
在现代软件开发中,RESTful API和Web服务均用于实现系统间通信,但各有特点。RESTful API遵循REST原则,主要使用HTTP/HTTPS协议,数据格式多为JSON或XML,适用于无状态通信;而Web服务包括SOAP和REST,常用于基于网络的API,采用标准化方法如WSDL或OpenAPI。理解两者区别有助于选择适合应用需求的解决方案,构建高效、可扩展的应用程序。

热门文章

最新文章