Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)...
Spring MVC 學(xué)習(xí)總結(jié)(九)——Spring MVC實(shí)現(xiàn)RESTful與JSON(Spring MVC為前端提供服務(wù))
目錄
- 一、JSON
- 1.1、概要
- 1.2、使用ModelAndView
- 1.3、使用@ResponseBody與Jackson
- 1.4、亂碼問題
- 1.4.1、方法一在action上聲明編碼格式
- 1.4.2、方法二修改Spring配置文件
- 1.5、日期格式化問題
- 1.5.1、方法一注解字段
- 1.5.2、方法二取消timestamps形式
- 1.6、工具類
- 1.7、數(shù)據(jù)持久化
- 1.7.1、創(chuàng)建數(shù)據(jù)庫(kù)與表
- 1.7.2、添加測(cè)試數(shù)據(jù)
- 1.7.3、添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)修改連接信息
- 1.7.4、新增UserDAOPro
- 1.7.5、修改用戶業(yè)務(wù)類
- 1.7.6、徹底解決Spring MVC 中文亂碼
- 二、RESTful
- 2.1、概要
- 2.2、@RestController
- 2.2.1、Hello World
- 2.3、RESTful員工管理示例
- 2.3.1、獲得所有的員工信息服務(wù)
- 2.3.2、獲得指定編號(hào)的員工信息服務(wù)
- 2.3.3、新增員工服務(wù)
- 2.3.4、修改員工服務(wù)
- 2.3.3、刪除員工服務(wù)
- 2.4、AJAX客戶端調(diào)用RESTful
- 2.4.1、用戶列表
- 2.4.2、新增用戶
- 2.4.3、刪除用戶
- 2.4.4、更新數(shù)據(jù)
- 三、示例下載
- 四、視頻
- 五、作業(yè)
- 六、工具下載
?很多時(shí)候前端都需要調(diào)用后臺(tái)服務(wù)實(shí)現(xiàn)交互功能,常見的數(shù)據(jù)交換格式多是JSON或XML,這里主要講解Spring MVC為前端提供JSON格式的數(shù)據(jù)并實(shí)現(xiàn)與前臺(tái)交互。RESTful則是一種軟件架構(gòu)風(fēng)格、設(shè)計(jì)風(fēng)格,而不是標(biāo)準(zhǔn),只是提供了一組設(shè)計(jì)原則和約束條件。它主要用于客戶端和服務(wù)器交互類的軟件。基于這個(gè)風(fēng)格設(shè)計(jì)的軟件可以更簡(jiǎn)潔,更有層次,更易于實(shí)現(xiàn)緩存等機(jī)制。
一、JSON
1.1、概要
JSON(JavaScript Object Notation, JS 對(duì)象標(biāo)記) 是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于 ECMAScript (w3c制定的js規(guī)范)的一個(gè)子集,采用完全獨(dú)立于編程語(yǔ)言的文本格式來(lái)存儲(chǔ)和表示數(shù)據(jù)。簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語(yǔ)言。 易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率。
在 JS 語(yǔ)言中,一切都是對(duì)象。因此,任何支持的類型都可以通過(guò) JSON 來(lái)表示,例如字符串、數(shù)字、對(duì)象、數(shù)組等。但是對(duì)象和數(shù)組是比較特殊且常用的兩種類型。
要實(shí)現(xiàn)從對(duì)象轉(zhuǎn)換為 JSON 字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //結(jié)果是 '{"a": "Hello", "b": "World"}'
要實(shí)現(xiàn)從 JSON 轉(zhuǎn)換為對(duì)象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //結(jié)果是 {a: 'Hello', b: 'World'}
示例:
?View Code結(jié)果:
1.2、使用ModelAndView
修改pom.xml添加對(duì)jackson的依賴
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.2</version></dependency>在user控制器中添加一個(gè)action
@RequestMapping(value = "/users")public ModelAndView users(){ModelAndView mav=new ModelAndView(new MappingJackson2JsonView());mav.addObject(userService.queryAllUsers());return mav;}運(yùn)行結(jié)果:
1.3、使用@ResponseBody與Jackson
修改pom.xml添加對(duì)jackson的依賴
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.2</version></dependency>添加一個(gè)action,使用注解@ResponseBody,響應(yīng)主體而不是路徑
@RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")@ResponseBodypublic String userJson(){ObjectMapper mapper=new ObjectMapper();try {return mapper.writeValueAsString(userService.queryAllUsers());} catch (JsonProcessingException e) {e.printStackTrace();}return null;}結(jié)果:
1.4、亂碼問題
1.4.1、方法一在action上聲明編碼格式
@RequestMapping(path="/json",produces = "application/json;charset=UTF-8")1.4.2、方法二修改Spring配置文件
上一種方法比較麻煩,如果項(xiàng)目中有許多action則每一個(gè)都要添加,可以通過(guò)Spring配置統(tǒng)一指定
<mvc:annotation-driven><mvc:message-converters register-defaults="true"><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg value="UTF-8"/></bean><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="objectMapper"><bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"><property name="failOnEmptyBeans" value="false"/></bean></property></bean></mvc:message-converters> </mvc:annotation-driven>1.5、日期格式化問題
默認(rèn)日期格式會(huì)變成一個(gè)數(shù)字,是1970年1月1日到當(dāng)前日期的毫秒數(shù):
Jackson 默認(rèn)是轉(zhuǎn)成timestamps形式
1.5.1、方法一注解字段
在實(shí)體字段上使用@JsonFormat注解格式化日期
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
代碼:
/*** 出生日期*/@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")private Date birthday;結(jié)果:
1.5.2、方法二取消timestamps形式
如果只取消則會(huì)得到一個(gè)默認(rèn)的日期格式,效果如下:
當(dāng)然自定義輸出格式是允許的
@RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")@ResponseBodypublic String userJson(){ObjectMapper mapper=new ObjectMapper();//不使用時(shí)間差的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定義日期格式對(duì)象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//指定日期格式mapper.setDateFormat(sdf);try {return mapper.writeValueAsString(userService.queryAllUsers());} catch (JsonProcessingException e) {e.printStackTrace();}return null;}運(yùn)行結(jié)果:
1.6、工具類
工具類可以復(fù)用代碼,提高開發(fā)效率,如上文中的序列化JSON:
package com.zhangguo.springmvc08.utils;import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;import java.text.SimpleDateFormat;/*** JSON工具類,輔助類* */ public class JsonUtil {public static String getJson(Object object) {return getJson(object,"yyyy-MM-dd HH:mm:ss");}public static String getJson(Object object,String dateFormat) {ObjectMapper mapper = new ObjectMapper();//不使用時(shí)間差的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定義日期格式對(duì)象SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);//指定日期格式mapper.setDateFormat(sdf);try {return mapper.writeValueAsString(object);} catch (JsonProcessingException e) {e.printStackTrace();}return null;} }調(diào)用:
@RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")@ResponseBodypublic String userJson(){return JsonUtil.getJson(userService.queryAllUsers(),"yyyy-MM-dd");}如對(duì)MySQL數(shù)據(jù)庫(kù)的訪問封裝:
?View Code1.7、數(shù)據(jù)持久化
上一章的示例中并沒有直接訪問數(shù)據(jù)庫(kù),數(shù)據(jù)以集合的形式存放在內(nèi)存中,這里使用MySQL將數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)中。該示例基于第8章的示例,請(qǐng)先熟悉第8章的內(nèi)容《Spring MVC 學(xué)習(xí)總結(jié)(八)——Spring MVC概要與環(huán)境配置(IDEA+Maven+Tomcat7+JDK8、示例與視頻)》
1.7.1、創(chuàng)建數(shù)據(jù)庫(kù)與表
開啟MySQL服務(wù)
打開管理工具Navicat
創(chuàng)建數(shù)據(jù)庫(kù)
新建表
/* Navicat MySQL Data TransferSource Server : localhostMe Source Server Version : 50506 Source Host : localhost:3306 Source Database : mvcdbTarget Server Type : MYSQL Target Server Version : 50506 File Encoding : 65001Date: 2017-12-07 14:08:35 */SET FOREIGN_KEY_CHECKS=0;-- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號(hào)',`name` varchar(32) NOT NULL COMMENT '姓名',`birthday` datetime DEFAULT NULL COMMENT '生日',`address` varchar(128) DEFAULT NULL COMMENT '地址',`phone` varchar(11) DEFAULT NULL COMMENT '電話',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of user -- ----------------------------1.7.2、添加測(cè)試數(shù)據(jù)
?
insert into user(name,birthday,address,phone) select '張學(xué)友','1968-09-08','中國(guó)香港','18989890098' union select '張惠妹','1969-01-05','中國(guó)北京','13345678781' union select '張國(guó)立',SYSDATE(),'中國(guó)珠海','13567453422'select id,name,birthday,address,phone from user;?
1.7.3、添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)修改連接信息
在pom.xml中依賴MySQL驅(qū)動(dòng)包
<!--mysql驅(qū)動(dòng)包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version></dependency>修改工具類的中數(shù)據(jù)庫(kù)連接信息
public static String DRIVER="com.mysql.jdbc.Driver";public static String URL="jdbc:mysql://127.0.0.1:3306/mvcdb?useUnicode=true&characterEncoding=UTF-8";public static String USER_NAME="root";public static String PASSWORD="pwd";1.7.4、新增UserDAOPro
?新增UserDAOPro類,實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)訪問,代碼如下:
package com.zhangguo.springmvc08.dao;import com.zhangguo.springmvc08.entity.User; import com.zhangguo.springmvc08.utils.JDBCUtil; import org.springframework.stereotype.Repository;import java.util.List;@Repository("mysql") public class UserDAOPro implements IUserDAO {public List<User> getAll() {return JDBCUtil.queryForList("select id,name,birthday,address,phone from user", User.class);}public User getUserById(int id) {return JDBCUtil.queryForObject("select id,name,birthday,address,phone from user where id=?", User.class, id);}public boolean add(User user) {return JDBCUtil.update("insert into user(name,birthday,address,phone) values(?,?,?,?)", user.getName(), user.getBirthday(), user.getAddress(), user.getPhone()) > 0;}public boolean delete(int id) {return JDBCUtil.update("delete from user where id=?", id) > 0;}public boolean update(User user) {return JDBCUtil.update("update user set name=?,birthday=?,address=?,phone=? where id=?", user.getName(), user.getBirthday(), user.getAddress(), user.getPhone(), user.getId()) > 0;} }1.7.5、修改用戶業(yè)務(wù)類
因?yàn)橄到y(tǒng)中有兩個(gè)類實(shí)現(xiàn)了IUserDAO,指定名稱:
package com.zhangguo.springmvc08.service;import com.zhangguo.springmvc08.dao.IUserDAO; import com.zhangguo.springmvc08.dao.UserDAO; import com.zhangguo.springmvc08.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service;import javax.annotation.Resource; import java.util.List;/**用戶業(yè)務(wù)*/ @Service public class UserService {@Resource(name="mysql")IUserDAO userdao;public List<User> queryAllUsers(){return userdao.getAll();}public User getUserById(int id){return userdao.getUserById(id);}public boolean deleteUser(int id){return userdao.delete(id);}public boolean addUser(User user){return userdao.add(user);}public boolean editUser(User user){return userdao.update(user);}}1.7.6、徹底解決Spring MVC 中文亂碼
添加用戶后發(fā)現(xiàn)有亂碼,調(diào)試發(fā)現(xiàn)發(fā)送到服務(wù)器的數(shù)據(jù)已經(jīng)是亂碼
1、頁(yè)面編碼
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>2、URL中的亂碼
改tomcat中server.xml中Connector的port=“8080”,加上一個(gè) URIEncoding=”utf-8”
3、配置過(guò)濾器,指定所有請(qǐng)求的編碼
修改web.xml,添加編碼過(guò)濾器
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>4、文件編碼
將文件另存為utf-8格式
5、數(shù)據(jù)庫(kù)編碼
連接字符串指定編碼格式
public static String URL="jdbc:mysql://127.0.0.1:3306/mvcdb?useUnicode=true&characterEncoding=UTF-8"創(chuàng)建數(shù)據(jù)庫(kù)時(shí)指定utf-8編碼格式
最終運(yùn)行結(jié)果正常:
二、RESTful
2.1、概要
REST(英文:Representational State Transfer,簡(jiǎn)稱REST,表述性狀態(tài)轉(zhuǎn)移)描述了一個(gè)架構(gòu)樣式的網(wǎng)絡(luò)系統(tǒng),比如 web 應(yīng)用程序。它首次出現(xiàn)在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規(guī)范的主要編寫者之一。在目前主流的三種Web服務(wù)交互方案中,REST相比于SOAP(Simple Object Access protocol,簡(jiǎn)單對(duì)象訪問協(xié)議)以及XML-RPC更加簡(jiǎn)單明了,無(wú)論是對(duì)URL的處理還是對(duì)Payload的編碼,REST都傾向于用更加簡(jiǎn)單輕量的方法設(shè)計(jì)和實(shí)現(xiàn)。值得注意的是REST并沒有一個(gè)明確的標(biāo)準(zhǔn),而更像是一種設(shè)計(jì)的風(fēng)格。
RESTful架構(gòu),就是目前最流行的一種互聯(lián)網(wǎng)軟件架構(gòu)。它結(jié)構(gòu)清晰、符合標(biāo)準(zhǔn)、易于理解、擴(kuò)展方便,所以正得到越來(lái)越多網(wǎng)站的采用。
GET /tickets # 獲取ticket列表
GET /tickets/12 # 查看某個(gè)具體的ticket
POST /tickets # 新建一個(gè)ticket
PUT /tickets/12 # 更新ticket 12.
DELETE /tickets/12 #刪除ticekt 12
REST特點(diǎn)如下:
- 基于HTTP協(xié)議
- 是另一種服務(wù)架構(gòu)
- 傳遞是JSON、POX(Plain Old XML)而不是SOAP格式的數(shù)據(jù)
- 充分利用HTTP謂詞(Verb)
- 側(cè)重?cái)?shù)據(jù)的傳輸,業(yè)務(wù)邏輯交給客戶端自行處理
REST是一種分布式服務(wù)架構(gòu)的風(fēng)格約束,像Java、.Net(WCF、WebAPI)都有對(duì)該約束的實(shí)現(xiàn),使URL變得更加有意義,更加簡(jiǎn)潔明了,如:
http://www.zhangguo.com/products/1 get請(qǐng)求 表示獲得所有產(chǎn)品的第1個(gè)
http://www.zhangguo.com/products/product post請(qǐng)求 表示添加一個(gè)產(chǎn)品
http://www.zhangguo.com/products/1/price get請(qǐng)求 表示獲得第1個(gè)產(chǎn)品的價(jià)格
http://www.zhangguo.com/products/1 delete請(qǐng)求 刪除編號(hào)為1的產(chǎn)品
REST設(shè)計(jì)需要遵循的原則:
- 網(wǎng)絡(luò)上的所有事物都被抽象為資源(resource);
- 每個(gè)資源對(duì)應(yīng)一個(gè)唯一的資源標(biāo)識(shí)符(resource identifier);
- 通過(guò)通用的連接器接口(generic connector interface)對(duì)資源進(jìn)行操作;
- 對(duì)資源的各種操作不會(huì)改變資源標(biāo)識(shí)符;
- 所有的操作都是無(wú)狀態(tài)的(stateless)
謂詞
GET
表示查詢操作,相當(dāng)于Retrieve、Select操作
POST
表示插入操作,相當(dāng)于Create,Insert操作
PUT
表示修改操作,相當(dāng)于Update操作
DELETE
表示刪除操作,相當(dāng)于Delete操作
其它還有:
2.2、@RestController
Spring 4.0重要的一個(gè)新的改進(jìn)是@RestController注解,它繼承自@Controller注解。4.0之前的版本,Spring MVC的組件都使用@Controller來(lái)標(biāo)識(shí)當(dāng)前類是一個(gè)控制器servlet。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController {String value() default ""; }使用這個(gè)注解,我們可以開發(fā)REST服務(wù)的時(shí)候不需要使用@Controller而專門的@RestController。
當(dāng)你實(shí)現(xiàn)一個(gè)RESTful web services的時(shí)候,response將一直通過(guò)response body發(fā)送。為了簡(jiǎn)化開發(fā),Spring 4.0提供了一個(gè)專門版本的controller。
添加了AsyncRestTemplate類,當(dāng)開發(fā)REST客戶端時(shí)允許非阻塞異步支持。
2.2.1、Hello World
默認(rèn)控制器與Action
package com.zhangguo.springmvc08.controller;import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;@Controller //聲明為控制器 @RequestMapping(path = {"/","Home","First"}) //請(qǐng)求映射 public class HomeController {@RequestMapping(path = "/index") //請(qǐng)求映射public String index(Model model){model.addAttribute("message","Hello Spring MVC!");return "home/index";}@RequestMapping(path = "/") //請(qǐng)求映射public String first(Model model){model.addAttribute("message","Hello Spring MVC,Welcome Page!");return "home/index";} }修改pom.xml添加jackson的引用
新增一個(gè)控制器,代碼如下:
package com.zhangguo.springmvc08.controller;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;@RestController @RequestMapping(path="/users") public class UsersController {@RequestMapping(path = "/{name}",method = RequestMethod.GET)public String hello(@PathVariable String name){return "Hello "+name;}@RequestMapping(path = "/stu/{name}",method = RequestMethod.GET)public Student student(@PathVariable String name){return new Student("Hello "+name);}}/**學(xué)生*/ class Student{public Student(String name) {this.name = name;}private String name;public String getName() {return name;}public void setName(String name) {this.name = name;} }運(yùn)行結(jié)果:
從上面的示例可以看出,使用@RestController后返回的字符串不再是路徑,如果返回的是對(duì)象則會(huì)直接序列化,可以是JSON或XML;如果返回的是對(duì)象類型則直接序列化成JSON格式,請(qǐng)注意添加對(duì)Jackson的依賴。
2.3、RESTful員工管理示例
假定要為員工(emp)提供對(duì)外的REST服務(wù),接口如下:
/emps? get 獲得所有的員工信息
/emps/1 get 獲得編號(hào)為1的員工信息
/emps post 添加
/emps put 修改
/emps/1 delete 刪除
2.3.1、獲得所有的員工信息服務(wù)
/emps? get 獲得所所有的員工信息
package com.zhangguo.springmvc08.controller;import com.zhangguo.springmvc08.entity.User; import com.zhangguo.springmvc08.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController @RequestMapping(path = "/emps") public class EmpController {@AutowiredUserService userService;@RequestMapping(path = "", method = RequestMethod.GET)public List<User> getAllemps() {return userService.queryAllUsers();}}?結(jié)果:
2.3.2、獲得指定編號(hào)的員工信息服務(wù)
/emps/1 get 獲得編號(hào)為1的員工信息
代碼:
@RequestMapping(path = "/{id}", method = RequestMethod.GET)public User getEmpById(@PathVariable int id) {return userService.getUserById(id);}結(jié)果:
2.3.3、新增員工服務(wù)
/emps post 添加
代碼:
@RequestMapping(path = "", method = RequestMethod.POST)public boolean addEmp(@RequestBody User user) {return userService.addUser(user);}請(qǐng)求:
返回true
結(jié)果:
說(shuō)明:參數(shù)中的json格式一定要使用標(biāo)準(zhǔn)格式,注意引號(hào),注意Content-Type,默認(rèn)的Content-Type類型是:application/x-www-form-urlencoded
因?yàn)槲覀兪褂胘son,則Content-Type的值應(yīng)該為application/json;charset=utf-8
2.3.4、修改員工服務(wù)
/emps? 修改 put請(qǐng)求
代碼:
@RequestMapping(path = "", method = RequestMethod.PUT)public boolean updateEmp(@RequestBody User user) {return userService.editUser(user);}測(cè)試:
結(jié)果:
2.3.3、刪除員工服務(wù)
/emps/1 delete 刪除
代碼:
package com.zhangguo.springmvc08.controller;import com.zhangguo.springmvc08.entity.User; import com.zhangguo.springmvc08.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;import java.util.List;@RestController @RequestMapping(path = "/emps") public class EmpController {@AutowiredUserService userService;@RequestMapping(path = "", method = RequestMethod.GET)public List<User> getAllEmps() {return userService.queryAllUsers();}@RequestMapping(path = "/{id}", method = RequestMethod.GET)public User getEmpById(@PathVariable int id) {return userService.getUserById(id);}@RequestMapping(path = "", method = RequestMethod.POST)public boolean addEmp(@RequestBody User user) {return userService.addUser(user);}@RequestMapping(path = "", method = RequestMethod.PUT)public boolean updateEmp(@RequestBody User user) {return userService.editUser(user);}@RequestMapping(path = "/{id}", method = RequestMethod.DELETE)public AjaxState deleteEmpById(@PathVariable int id) {Boolean result=userService.deleteUser(id);return new AjaxState(result?"success":"error",id,result?"刪除成功!":"刪除失敗");}}class AjaxState{public String state;public Object data;public String message;public AjaxState(String state, Object data, String message) {this.state = state;this.data = data;this.message = message;}public AjaxState(){} }測(cè)試:
結(jié)果:
已刪除成功,delete請(qǐng)求不需要正文與get請(qǐng)求類似
2.4、AJAX客戶端調(diào)用RESTful
ajax傳送json格式數(shù)據(jù),關(guān)鍵是指定contentType,data要是json格式
如果是restful接口,把type改成對(duì)應(yīng)的post(增)、delete(刪)、put(改)、get(查)即可
var post_data={"name":"test001","pass":"xxxx"}; $.ajax({ url: "http://192.168.10.111:8080/uc/login", type: 'post', contentType: "application/json; charset=utf-8", data:JSON.stringify(post_data), success:function (data) { //調(diào)用成功 }, error: function(data, textStatus, errorThrown){ //調(diào)用失敗 } });為了前端統(tǒng)一調(diào)用,修改后的控制器如下:
package com.zhangguo.springmvc08.controller;import com.zhangguo.springmvc08.entity.User; import com.zhangguo.springmvc08.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;import java.util.List;@RestController @RequestMapping(path = "/emps") public class EmpController extends BaseController {@AutowiredUserService userService;@RequestMapping(path = "", method = RequestMethod.GET)public AjaxState getAllEmps() {List<User> users=userService.queryAllUsers();boolean result=users!=null;return new AjaxState(result?"success":"error",users,result?"獲得數(shù)據(jù)成功!":"獲得數(shù)據(jù)失敗!");}@RequestMapping(path = "/{id}", method = RequestMethod.GET)public AjaxState getEmpById(@PathVariable int id) {User user=userService.getUserById(id);boolean result=user!=null;return new AjaxState(result?"success":"error",user,result?"獲得數(shù)據(jù)成功!":"獲得數(shù)據(jù)失敗!");}@RequestMapping(path = "", method = RequestMethod.POST)public AjaxState addEmp(@RequestBody User user) {boolean result=userService.addUser(user);return new AjaxState(result?"success":"error",user,result?"添加成功!":"添加失敗");}@RequestMapping(path = "", method = RequestMethod.PUT)public AjaxState updateEmp(@RequestBody User user) {boolean result=userService.editUser(user);return new AjaxState(result?"success":"error",user,result?"修改成功!":"修改失敗");}@RequestMapping(path = "/{id}", method = RequestMethod.DELETE)public AjaxState deleteEmpById(@PathVariable int id) {Boolean result=userService.deleteUser(id);return new AjaxState(result?"success":"error",id,result?"刪除成功!":"刪除失敗");}}class AjaxState{public String state;public Object data;public String message;public AjaxState(String state, Object data, String message) {this.state = state;this.data = data;this.message = message;}public AjaxState(){} }2.4.1、用戶列表
示例:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"/><title>Title</title> </head> <body> <h2>員工管理</h2> <table border="1" width="100%" id="tabEmps"><tr><th>編號(hào)</th><th>姓名</th><th>生日</th><th>地址</th><th>電話</th><th>操作</th></tr> </table> <p></p> <p class="loading" style="display: none;"><img src="img/loading.gif" align="absmiddle">努力加載中... </p> <p class="message"></p> <script src="js/jquery-1.11.3.min.js"></script> <script> // var data = { // "state": "success", // "data": {"id": 1, "name": "張學(xué)友", "birthday": -41500800000, "address": "中國(guó)香港", "phone": "18989890098"}, // "message": "獲得數(shù)據(jù)成功!" // }var app = {url: "http://localhost:8080/mvc08/emps",init:function(){this.binddata();},ajax: function (actionType, callback, path, data) {$.ajax({url: app.url + (path||""),contentType: "application/json;charset=utf-8",data: data || {},type: actionType||"get",dataType: "json",success: function (data) {if(data&&data.state=="success"){app.info(data.message);}else if(data&&data.state=="error"){app.info(data.message);}else{app.info(data);}if(callback){callback(data);}},error: function (XMLHttpRequest, textStatus, errorThrown) {info(textStatus+errorThrown);},beforeSend: function () {$(".loading").show(200);},complete: function () {$(".loading").hide(200);}});},binddata: function () {this.ajax("get",function(data){$.each(data.data,function(index,emp){var tr=$("<tr/>").appendTo("#tabEmps");$("<td/>").text(emp.id).appendTo(tr);$("<td/>").text(emp.name).appendTo(tr);$("<td/>").text(emp.birthday).appendTo(tr);$("<td/>").text(emp.address).appendTo(tr);$("<td/>").text(emp.phone).appendTo(tr);$("<td/>").html("<a>刪除</a>").appendTo(tr);});});},info:function(msg){$(".message")[0].innerHTML+=msg+"<br/>";}};app.init(); </script> </body> </html>結(jié)果:
2.4.2、新增用戶
示例:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"/><title>Title</title> </head> <body> <h2>員工管理</h2> <table border="1" width="100%" id="tabEmps"><tr><th>編號(hào)</th><th>姓名</th><th>生日</th><th>地址</th><th>電話</th><th>操作</th></tr> </table> <p class="loading" style="display: none;"><img src="img/loading.gif" align="absmiddle">努力加載中... </p> <form id="formEmps"><fieldset><legend>用戶信息</legend><p><label for="name">姓名:</label><input name="name" id="name" type="text" required="required" maxlength="32"/></p><p><label for="birthday">生日:</label><input name="birthday" id="birthday" type="date" required="required" maxlength="8"/></p><p><label for="address">地址:</label><input name="address" id="address" type="text" required="required" maxlength="128"/></p><p><label for="phone">電話:</label><input name="phone" id="phone" type="text" required="required" maxlength="11"/></p><p><input id="id" type="hidden" name="id" value=""/><button type="button" id="btnSubmit">保存</button></p></fieldset> </form> <p class="message"> </p> <script src="js/jquery-1.11.3.min.js"></script> <script>// var data = {// "state": "success",// "data": {"id": 1, "name": "張學(xué)友", "birthday": -41500800000, "address": "中國(guó)香港", "phone": "18989890098"},// "message": "獲得數(shù)據(jù)成功!"// }var app = {url: "http://localhost:8080/mvc08/emps",init: function () {$("#btnSubmit").click(app.save);this.binddata();},ajax: function (actionType, callback, path, data) {$.ajax({url: app.url + (path || ""),contentType: "application/json;charset=utf-8",data:JSON.stringify(data)||"{}",type: actionType || "get",dataType: "json",success: function (data) {if (data && data.state == "success") {app.info(data.message);} else if (data && data.state == "error") {app.info(data.message);} else {app.info(data);}if (callback) {callback(data);}},error: function (XMLHttpRequest, textStatus, errorThrown) {app.info(textStatus + errorThrown);},beforeSend: function () {$(".loading").show(200);},complete: function () {$(".loading").hide(200);}});},binddata: function () {$("#tabEmps tr:gt(0)").remove();this.ajax("get", function (data) {$.each(data.data, function (index, emp) {var tr = $("<tr/>").appendTo("#tabEmps");$("<td/>").text(emp.id).appendTo(tr);$("<td/>").text(emp.name).appendTo(tr);$("<td/>").text(emp.birthday).appendTo(tr);$("<td/>").text(emp.address).appendTo(tr);$("<td/>").text(emp.phone).appendTo(tr);$("<td/>").html("<a>刪除</a>").appendTo(tr);});});},getEmp:function(){return {"id":$("#id").val(),"name":$("#name").val(),"birthday":$("#birthday").val(),"address":$("#address").val(),"phone":$("#phone").val()};},save:function(){var emp=app.getEmp();if(emp.id){app.update(emp);}else{app.add(emp);}},add:function(emp){app.ajax("POST",function (data) {app.binddata();},"",emp);},update:function(emp){app.ajax("Put",function (data) {app.binddata();},"",emp);},info: function (msg) {$(".message")[0].innerHTML += msg + "<br/>";}};app.init(); </script> </body> </html>結(jié)果:
2.4.3、刪除用戶
示例:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"/><title>Title</title> </head> <body> <h2>員工管理</h2> <table border="1" width="100%" id="tabEmps"><tr><th>編號(hào)</th><th>姓名</th><th>生日</th><th>地址</th><th>電話</th><th>操作</th></tr> </table> <p class="loading" style="display: none;"><img src="img/loading.gif" align="absmiddle">努力加載中... </p> <form id="formEmps"><fieldset><legend>用戶信息</legend><p><label for="name">姓名:</label><input name="name" id="name" type="text" required="required" maxlength="32"/></p><p><label for="birthday">生日:</label><input name="birthday" id="birthday" type="date" required="required" maxlength="8"/></p><p><label for="address">地址:</label><input name="address" id="address" type="text" required="required" maxlength="128"/></p><p><label for="phone">電話:</label><input name="phone" id="phone" type="text" required="required" maxlength="11"/></p><p><input id="id" type="hidden" name="id" value=""/><button type="button" id="btnSubmit">保存</button></p></fieldset> </form> <p class="message"> </p> <script src="js/jquery-1.11.3.min.js"></script> <script>// var data = {// "state": "success",// "data": {"id": 1, "name": "張學(xué)友", "birthday": -41500800000, "address": "中國(guó)香港", "phone": "18989890098"},// "message": "獲得數(shù)據(jù)成功!"// }var app = {url: "http://localhost:8080/mvc08/emps",init: function () {$("#btnSubmit").click(app.save);$("#tabEmps").on("click", ".del", app.delete);this.binddata();},ajax: function (actionType, callback, path, data) {$.ajax({url: app.url + (path || ""),contentType: "application/json;charset=utf-8",data: JSON.stringify(data) || "{}",type: actionType || "get",dataType: "json",success: function (data) {if (data && data.state == "success") {app.info(data.message);} else if (data && data.state == "error") {app.info(data.message);} else {app.info(data);}if (callback) {callback(data);}},error: function (XMLHttpRequest, textStatus, errorThrown) {app.info(textStatus + errorThrown);},beforeSend: function () {$(".loading").show(200);},complete: function () {$(".loading").hide(200);}});},binddata: function () {$("#tabEmps tr:gt(0)").remove();this.ajax("get", function (data) {$.each(data.data, function (index, emp) {var tr = $("<tr/>").data("emp", emp).appendTo("#tabEmps");$("<td/>").text(emp.id).appendTo(tr);$("<td/>").text(emp.name).appendTo(tr);$("<td/>").text(emp.birthday).appendTo(tr);$("<td/>").text(emp.address).appendTo(tr);$("<td/>").text(emp.phone).appendTo(tr);$("<td/>").html("<a class='del' href='#'>刪除</a>").appendTo(tr);});});},getEmp: function () {return {"id": $("#id").val(),"name": $("#name").val(),"birthday": $("#birthday").val(),"address": $("#address").val(),"phone": $("#phone").val()};},save: function () {var emp = app.getEmp();if (emp.id) {app.update(emp);} else {app.add(emp);}},add: function (emp) {app.ajax("POST", function (data) {app.binddata();}, "", emp);},update: function (emp) {app.ajax("Put", function (data) {app.binddata();}, "", emp);},delete: function () {if (confirm("刪除嗎?")) {var tr = $(this).closest("tr");var emp = tr.data("emp");app.ajax("DELETE", function (data) {tr.remove();}, "/" + emp.id);}},info: function (msg) {$(".message")[0].innerHTML += msg + "<br/>";}};app.init(); </script> </body> </html>結(jié)果:
2.4.4、更新數(shù)據(jù)
示例:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"/><title>Title</title> </head> <body> <h2>員工管理</h2> <table border="1" width="100%" id="tabEmps"><tr><th>編號(hào)</th><th>姓名</th><th>生日</th><th>地址</th><th>電話</th><th>操作</th></tr> </table> <p class="loading" style="display: none;"><img src="img/loading.gif" align="absmiddle">努力加載中... </p> <form id="formEmps"><fieldset><legend>用戶信息</legend><p><label for="name">姓名:</label><input name="name" id="name" type="text" required="required" maxlength="32"/></p><p><label for="birthday">生日:</label><input name="birthday" id="birthday" type="date" required="required" maxlength="8"/></p><p><label for="address">地址:</label><input name="address" id="address" type="text" required="required" maxlength="128"/></p><p><label for="phone">電話:</label><input name="phone" id="phone" type="text" required="required" maxlength="11"/></p><p><input id="id" type="hidden" name="id" value=""/><button type="button" id="btnSubmit">保存</button></p></fieldset> </form> <p class="message"> </p> <script src="js/jquery-1.11.3.min.js"></script> <script>// var data = {// "state": "success",// "data": {"id": 1, "name": "張學(xué)友", "birthday": -41500800000, "address": "中國(guó)香港", "phone": "18989890098"},// "message": "獲得數(shù)據(jù)成功!"// }var app = {url: "http://localhost:8080/mvc08/emps",init: function () {$("#btnSubmit").click(app.save);$("#tabEmps").on("click", ".del", app.delete);$("#tabEmps").on("click", ".edit", app.edit);this.binddata();},ajax: function (actionType, callback, path, data) {$.ajax({url: app.url + (path || ""),contentType: "application/json;charset=utf-8",data: JSON.stringify(data) || "{}",type: actionType || "get",dataType: "json",success: function (data) {if (data && data.state == "success") {app.info(data.message);} else if (data && data.state == "error") {app.info(data.message);} else {app.info(data);}if (callback) {callback(data);}},error: function (XMLHttpRequest, textStatus, errorThrown) {app.info(textStatus + errorThrown);},beforeSend: function () {$(".loading").show(200);},complete: function () {$(".loading").hide(200);}});},binddata: function () {$("#tabEmps tr:gt(0)").remove();this.ajax("get", function (data) {$.each(data.data, function (index, emp) {var tr = $("<tr/>").data("emp", emp).appendTo("#tabEmps");$("<td/>").text(emp.id).appendTo(tr);$("<td/>").text(emp.name).appendTo(tr);$("<td/>").text(emp.birthday).appendTo(tr);$("<td/>").text(emp.address).appendTo(tr);$("<td/>").text(emp.phone).appendTo(tr);$("<td/>").html("<a class='del' href='#'>刪除</a> | <a class='edit' href='#'>編輯</a>").appendTo(tr);});});},getEmp: function () {return {"id": $("#id").val(),"name": $("#name").val(),"birthday": $("#birthday").val(),"address": $("#address").val(),"phone": $("#phone").val()};},save: function () {var emp = app.getEmp();if (emp.id) {$("#id").val("");app.update(emp);} else {app.add(emp);}},add: function (emp) {app.ajax("POST", function (data) {app.binddata();}, "", emp);},update: function (emp) {app.ajax("Put", function (data) {app.binddata();}, "", emp);},delete: function () {if (confirm("刪除嗎?")) {var tr = $(this).closest("tr");var emp = tr.data("emp");app.ajax("DELETE", function (data) {tr.remove();}, "/" + emp.id);}},edit:function(){var emp = $(this).closest("tr").data("emp");$("#id").val(emp.id);$("#name").val(emp.name);$("#birthday").val(emp.birthday);$("#address").val(emp.address);$("#phone").val(emp.phone);},info: function (msg) {$(".message")[0].innerHTML += msg + "<br/>";}};app.init(); </script> </body> </html>結(jié)果:
三、示例下載
https://git.coding.net/zhangguo5/SpringMVC08.git
四、視頻
https://www.bilibili.com/video/av16991874/
五、作業(yè)
5.1、請(qǐng)練習(xí)上課示例
5.2、請(qǐng)使用Spring MVC對(duì)外提供商品(Product)的管理接口,如:
product/list 獲得所有商品 get
product/1 獲得編號(hào)為1的商品 get
product/delete/1 刪除編號(hào)為1的商品 get
product/insert 新增商品 post
product/edit 編輯商品 post
使用AJAX調(diào)用發(fā)布的服務(wù),實(shí)現(xiàn)如下功能,驗(yàn)證、搜索、多刪除功能選作。
5.3、請(qǐng)完成一個(gè)前后臺(tái)分離的汽車管理系統(tǒng)(CarSystem),需要管理汽車的(車牌、顏色、價(jià)格、出廠日期、排量),要求完成CRUD功能,界面美觀大方。
a)、請(qǐng)使用MySQL數(shù)據(jù)庫(kù)創(chuàng)建庫(kù)與表(CarSystem)
b)、使用Spring MVC定義5個(gè)RESTful服務(wù),注意路徑格式,先用fiddler測(cè)試通過(guò)。
c)、定義car.html頁(yè)面,使用jQuery插件中的ajax功能消費(fèi)RESTful服務(wù)實(shí)現(xiàn)功能,反復(fù)測(cè)試。
六、工具下載
Fiddler2(漢化版)?鏈接: https://pan.baidu.com/s/1mhNTg1M 密碼: qiib
轉(zhuǎn)載于:https://www.cnblogs.com/liujiandejava/p/9359647.html
總結(jié)
以上是生活随笔為你收集整理的Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: scipy的一些函数名
- 下一篇: 小红帽(RedHat)按装