CRUD using Spring MVC 4.0 RESTful Web Services and AngularJS

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 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!

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
58 4
|
2月前
|
Java API 数据库
如何使用Spring Boot构建RESTful API,以在线图书管理系统为例
【10月更文挑战第9天】本文介绍了如何使用Spring Boot构建RESTful API,以在线图书管理系统为例,从项目搭建、实体类定义、数据访问层创建、业务逻辑处理到RESTful API的实现,详细展示了每个步骤。通过Spring Boot的简洁配置和强大功能,开发者可以高效地开发出功能完备、易于维护的Web应用。
71 3
|
1月前
|
JSON API 数据格式
如何使用Python和Flask构建一个简单的RESTful API。Flask是一个轻量级的Web框架
本文介绍了如何使用Python和Flask构建一个简单的RESTful API。Flask是一个轻量级的Web框架,适合小型项目和微服务。文章从环境准备、创建基本Flask应用、定义资源和路由、请求和响应处理、错误处理等方面进行了详细说明,并提供了示例代码。通过这些步骤,读者可以快速上手构建自己的RESTful API。
49 2
|
2月前
|
XML 关系型数据库 MySQL
Web Services 服务 是不是过时了?创建 Web Services 服务实例
本文讨论了WebServices(基于SOAP协议)与WebAPI(基于RESTful)在开发中的应用,回顾了WebServices的历史特点,比较了两者在技术栈、轻量化和适用场景的差异,并分享了使用VB.net开发WebServices的具体配置步骤和疑问。
38 0
|
3月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
72 7
|
3月前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
79 2
|
3月前
|
前端开发 测试技术 开发者
MVC模式在现代Web开发中有哪些优势和局限性?
MVC模式在现代Web开发中有哪些优势和局限性?
|
4月前
|
Java API 数据库
【神操作!】Spring Boot打造RESTful API:从零到英雄,只需这几步,让你的Web应用瞬间飞起来!
【8月更文挑战第12天】构建RESTful API是现代Web开发的关键技术之一。Spring Boot因其实现简便且功能强大而深受开发者喜爱。本文以在线图书管理系统为例,展示了如何利用Spring Boot快速构建RESTful API。从项目初始化、实体定义到业务逻辑处理和服务接口实现,一步步引导读者完成API的搭建。通过集成JPA进行数据库操作,以及使用控制器类暴露HTTP端点,最终实现了书籍信息的增删查改功能。此过程不仅高效直观,而且易于维护和扩展。
72 1
|
4月前
|
开发者 前端开发 Java
架构模式的诗与远方:如何在MVC的田野上,用Struts 2编织Web开发的新篇章
【8月更文挑战第31天】架构模式是软件开发的核心概念,MVC(Model-View-Controller)通过清晰的分层和职责分离,成为广泛采用的模式。随着业务需求的复杂化,Struts 2框架应运而生,继承MVC优点并引入更多功能。本文探讨从MVC到Struts 2的演进,强调架构模式的重要性。MVC将应用程序分为模型、视图和控制器三部分,提高模块化和可维护性。
50 0
|
4月前
|
Java 网络架构 数据格式
Struts 2 携手 RESTful:颠覆传统,重塑Web服务新纪元的史诗级组合!
【8月更文挑战第31天】《Struts 2 与 RESTful 设计:构建现代 Web 服务》介绍如何结合 Struts 2 框架与 RESTful 设计理念,构建高效、可扩展的 Web 服务。Struts 2 的 REST 插件提供简洁的 API 和约定,使开发者能快速创建符合 REST 规范的服务接口。通过在 `struts.xml` 中配置 `&lt;rest&gt;` 命名空间并使用注解如 `@Action`、`@GET` 等,可轻松定义服务路径及 HTTP 方法。
67 0