很多时候前端都需要调用后台服务实现交互功能,常见的数据交换格式多是JSON或XML,这里主要讲解Spring MVC为前端提供JSON格式的数据并实现与前台交互。RESTful则是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。
要实现从对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
要实现从 JSON 转换为对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
示例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>
- </title>
- <!--[if lte IE 8]>
- <script type="text/javascript" src="//res.wx.qq.com/a/wx_fed/webwx/res/json3.min.js">
- </script>
- <![endif]-->
- </head>
- <body>
- <script type="text/javascript">
- //js对象
- var user = {
- "name": "张学友",
- "address": "中国香港"
- };
- //将对象转换成字符
- var str = JSON.stringify(user);
- alert(str);
- //将字符串转换成json对象
- var zxy = JSON.parse(str);
- alert(zxy.name + "," + zxy.address);
- </script>
- </body>
- </html>
结果:
修改pom.xml添加对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控制器中添加一个action
- @RequestMapping(value = "/users")
- public ModelAndView users(){
- ModelAndView mav=new ModelAndView(new MappingJackson2JsonView());
- mav.addObject(userService.queryAllUsers());
- return mav;
- }
运行结果:
修改pom.xml添加对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>
添加一个action,使用注解@ResponseBody,响应主体而不是路径
- @RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")
- @ResponseBody
- public String userJson(){
- ObjectMapper mapper=new ObjectMapper();
- try {
- return mapper.writeValueAsString(userService.queryAllUsers());
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- return null;
- }
结果:
- @RequestMapping(path = "/json", produces = "application/json;charset=UTF-8")
上一种方法比较麻烦,如果项目中有许多action则每一个都要添加,可以通过Spring配置统一指定
- <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>
默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数:
Jackson 默认是转成timestamps形式
在实体字段上使用@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;
结果:
如果只取消则会得到一个默认的日期格式,效果如下:
当然自定义输出格式是允许的
- @RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")
- @ResponseBody
- public String userJson(){
- ObjectMapper mapper=new ObjectMapper();
- //不使用时间差的方式
- mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- //自定义日期格式对象
- 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;
- }
运行结果:
工具类可以复用代码,提高开发效率,如上文中的序列化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();
- //不使用时间差的方式
- mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- //自定义日期格式对象
- SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
- //指定日期格式
- mapper.setDateFormat(sdf);
- try {
- return mapper.writeValueAsString(object);
- } catch(JsonProcessingException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
调用:
- @RequestMapping(value = "/userJson",produces = "application/json;charset=utf-8")
- @ResponseBody
- public String userJson(){
- return JsonUtil.getJson(userService.queryAllUsers(),"yyyy-MM-dd");
- }
如对MySQL数据库的访问封装:
- package com.zhangguo.springmvc08.utils;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- public class JDBCUtil {
- public static String DRIVER = "com.mysql.jdbc.Driver";
- public static String URL = "jdbc:mysql://127.0.0.1:3306/schoolmis?useUnicode=true&characterEncoding=UTF-8";
- public static String USER_NAME = "root";
- public static String PASSWORD = "pwd";
- //加载驱动
- static {
- try {
- Class.forName(DRIVER);
- } catch(ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- private JDBCUtil() {
- }
- /**
- * 获得连接
- *
- * @return
- */
- public static Connection getconnnection() {
- Connection con = null;
- try {
- con = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
- } catch(SQLException e) {
- e.printStackTrace();
- }
- return con;
- }
- /**
- * 关闭连接
- *
- * @param rs
- * @param st
- * @param con
- */
- public static void close(ResultSet rs, Statement st, Connection con) {
- try {
- try {
- if (rs != null) {
- rs.close();
- }
- } finally {
- try {
- if (st != null) {
- st.close();
- }
- } finally {
- if (con != null) con.close();
- }
- }
- } catch(SQLException e) {
- e.printStackTrace();
- }
- }
- /**
- * 关闭连接
- *
- * @param rs
- */
- public static void close(ResultSet rs) {
- Statement st = null;
- Connection con = null;
- try {
- try {
- if (rs != null) {
- st = rs.getStatement();
- rs.close();
- }
- } finally {
- try {
- if (st != null) {
- con = st.getConnection();
- st.close();
- }
- } finally {
- if (con != null) {
- con.close();
- }
- }
- }
- } catch(SQLException e) {
- e.printStackTrace();
- }
- }
- /**
- * 关闭连接
- *
- * @param st
- * @param con
- */
- public static void close(Statement st, Connection con) {
- try {
- try {
- if (st != null) {
- st.close();
- }
- } finally {
- if (con != null) con.close();
- }
- } catch(SQLException e) {
- e.printStackTrace();
- }
- }
- /**
- * insert/update/delete
- * 增加/更新/删除
- *
- * @param sql 数据库语句
- * @param args 可变参数(可以不带参数,可以带0-n个参数)
- * @return
- */
- public static int update(String sql, Object...args) {
- int result = 0;
- Connection con = getconnnection();
- PreparedStatement ps = null;
- try {
- ps = con.prepareStatement(sql);
- if (args != null) {
- for (int i = 0; i < args.length; i++) {
- ps.setObject((i + 1), args[i]);
- }
- }
- result = ps.executeUpdate();
- } catch(SQLException e) {
- e.printStackTrace();
- } finally {
- close(ps, con);
- }
- return result;
- }
- /**
- * query, because need to manually close the resource, so not recommended
- * for use it
- *
- * @param sql
- * @param args
- * @return ResultSet
- */
- @Deprecated //注解
- public static ResultSet query(String sql, Object...args) {
- ResultSet result = null;
- Connection con = getconnnection();
- PreparedStatement ps = null;
- try {
- ps = con.prepareStatement(sql);
- if (args != null) {
- for (int i = 0; i < args.length; i++) {
- ps.setObject((i + 1), args[i]);
- }
- }
- result = ps.executeQuery();
- } catch(SQLException e) {
- e.printStackTrace();
- }
- return result;
- }
- /**
- * Query a single record
- * 查询单个记录
- * @param sql
- * @param args
- * @return Map<String,Object>
- */
- public static Map < String,
- Object > queryForMap(String sql, Object...args) {
- Map < String,
- Object > result = new HashMap < String,
- Object > ();
- List < Map < String,
- Object >> list = queryForList(sql, args);
- if (list.size() > 0) {
- result = list.get(0);
- }
- return result;
- }
- /**
- * Query a single record
- * 查询单个记录返回强类型对象
- * @param sql
- * @param args
- * @return <T> //泛型
- */
- public static < T > T queryForObject(String sql, Class < T > clz, Object...args) {
- T result = null;
- List < T > list = queryForList(sql, clz, args);
- if (list.size() > 0) {
- result = list.get(0);
- }
- return result;
- }
- /**
- * Query a single record
- *
- * @param sql
- * @param args
- * @return List<Map<String,Object>>
- */
- public static List < Map < String,
- Object >> queryForList(String sql, Object...args) {
- List < Map < String,
- Object >> result = new ArrayList < Map < String,
- Object >> ();
- Connection con = null;
- ResultSet rs = null;
- PreparedStatement ps = null;
- try {
- con = getconnnection();
- ps = con.prepareStatement(sql);
- if (args != null) {
- for (int i = 0; i < args.length; i++) {
- ps.setObject((i + 1), args[i]);
- }
- }
- rs = ps.executeQuery();
- ResultSetMetaData rsmd = rs.getMetaData();
- int columnCount = rsmd.getColumnCount();
- while (rs.next()) {
- Map < String,
- Object > map = new HashMap < String,
- Object > ();
- for (int i = 1; i <= columnCount; i++) {
- map.put(rsmd.getColumnLabel(i), rs.getObject(i));
- }
- result.add(map);
- }
- } catch(SQLException e) {
- e.printStackTrace();
- } finally {
- close(rs, ps, con);
- }
- return result;
- }
- /**
- * Query records
- * 查询多个对象,返回强类型集合
- * @param sql
- * @param args
- * @return List<T>
- */
- public static < T > List < T > queryForList(String sql, Class < T > clz, Object...args) {
- List < T > result = new ArrayList < T > ();
- Connection con = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- con = getconnnection();
- ps = con.prepareStatement(sql);
- if (args != null) {
- for (int i = 0; i < args.length; i++) {
- ps.setObject((i + 1), args[i]);
- }
- }
- rs = ps.executeQuery();
- ResultSetMetaData rsmd = rs.getMetaData();
- int columnCount = rsmd.getColumnCount();
- while (rs.next()) {
- T obj = clz.newInstance();
- for (int i = 1; i <= columnCount; i++) {
- String columnName = rsmd.getColumnName(i);
- String methodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1, columnName.length());
- Method method[] = clz.getMethods();
- for (Method meth: method) {
- if (methodName.equals(meth.getName())) {
- meth.invoke(obj, rs.getObject(i));
- }
- }
- }
- result.add(obj);
- }
- } catch(InstantiationException e) {
- e.printStackTrace();
- } catch(IllegalAccessException e) {
- e.printStackTrace();
- } catch(SQLException e) {
- e.printStackTrace();
- } catch(IllegalArgumentException e) {
- e.printStackTrace();
- } catch(InvocationTargetException e) {
- e.printStackTrace();
- } finally {
- close(rs, ps, con);
- }
- return result;
- }
- }
上一章的示例中并没有直接访问数据库,数据以集合的形式存放在内存中,这里使用MySQL将数据存储到数据库中。该示例基于第8章的示例,请先熟悉第8章的内容《Spring MVC 学习总结(八)——Spring MVC概要与环境配置(IDEA+Maven+Tomcat7+JDK8、示例与视频)》
开启MySQL服务
打开管理工具Navicat
创建数据库
新建表
- /*
- Navicat MySQL Data Transfer
- Source Server : localhostMe
- Source Server Version : 50506
- Source Host : localhost:3306
- Source Database : mvcdb
- Target Server Type : MYSQL
- Target Server Version : 50506
- File Encoding : 65001
- Date: 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 '编号',
- `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
- -- ----------------------------
- insert into user(name,birthday,address,phone)
- select '张学友','1968-09-08','中国香港','18989890098' union
- select '张惠妹','1969-01-05','中国北京','13345678781' union
- select '张国立',SYSDATE(),'中国珠海','13567453422'
- select id,name,birthday,address,phone from user;
在pom.xml中依赖MySQL驱动包
- <!--mysql驱动包-->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.35</version>
- </dependency>
修改工具类的中数据库连接信息
- 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";
新增UserDAOPro类,实现MySQL数据库访问,代码如下:
- 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;
- }
- }
因为系统中有两个类实现了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;
- /**用户业务*/
- @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、页面编码
- <%@ 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”,加上一个 URIEncoding=”utf-8”
3、配置过滤器,指定所有请求的编码
修改web.xml,添加编码过滤器
- <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、数据库编码
连接字符串指定编码格式
- public static String URL = "jdbc:mysql://127.0.0.1:3306/mvcdb?useUnicode=true&characterEncoding=UTF-8"
创建数据库时指定utf-8编码格式
最终运行结果正常:
REST(英文:Representational State Transfer,简称REST,表述性状态转移)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。
RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
GET /tickets # 获取ticket列表
GET /tickets/12 # 查看某个具体的ticket
POST /tickets # 新建一个ticket
PUT /tickets/12 # 更新ticket 12.
DELETE /tickets/12 #删除ticekt 12
REST特点如下:
REST是一种分布式服务架构的风格约束,像Java、.Net(WCF、WebAPI)都有对该约束的实现,使URL变得更加有意义,更加简洁明了,如:
http://www.zhangguo.com/products/1 get请求 表示获得所有产品的第1个
http://www.zhangguo.com/products/product post请求 表示添加一个产品
http://www.zhangguo.com/products/1/price get请求 表示获得第1个产品的价格
http://www.zhangguo.com/products/1 delete请求 删除编号为1的产品
REST设计需要遵循的原则:
谓词
GET
表示查询操作,相当于Retrieve、Select操作
POST
表示插入操作,相当于Create,Insert操作
PUT
表示修改操作,相当于Update操作
DELETE
表示删除操作,相当于Delete操作
其它还有:
Spring 4.0重要的一个新的改进是@RestController注解,它继承自@Controller注解。4.0之前的版本,Spring MVC的组件都使用@Controller来标识当前类是一个控制器servlet。
- @Target({ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Controller
- @ResponseBody
- public @interface RestController {
- String value() default "";
- }
使用这个注解,我们可以开发REST服务的时候不需要使用@Controller而专门的@RestController。
当你实现一个RESTful web services的时候,response将一直通过response body发送。为了简化开发,Spring 4.0提供了一个专门版本的controller。
添加了AsyncRestTemplate类,当开发REST客户端时允许非阻塞异步支持。
默认控制器与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"}) //请求映射
- public class HomeController {
- @RequestMapping(path = "/index") //请求映射
- public String index(Model model){
- model.addAttribute("message","Hello Spring MVC!");
- return "home/index";
- }
- @RequestMapping(path = "/") //请求映射
- public String first(Model model){
- model.addAttribute("message","Hello Spring MVC,Welcome Page!");
- return "home/index";
- }
- }
修改pom.xml添加jackson的引用
新增一个控制器,代码如下:
- 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);
- }
- }
- /**学生*/
- 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;
- }
- }
运行结果:
从上面的示例可以看出,使用@RestController后返回的字符串不再是路径,如果返回的是对象则会直接序列化,可以是JSON或XML;如果返回的是对象类型则直接序列化成JSON格式,请注意添加对Jackson的依赖。
假定要为员工(emp)提供对外的REST服务,接口如下:
/emps get 获得所有的员工信息
/emps/1 get 获得编号为1的员工信息
/emps post 添加
/emps put 修改
/emps/1 delete 删除
/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 {
- @Autowired
- UserService userService;
- @RequestMapping(path = "", method = RequestMethod.GET)
- public List<User> getAllemps() {
- return userService.queryAllUsers();
- }
- }
结果:
/emps/1 get 获得编号为1的员工信息
代码:
- @RequestMapping(path = "/{id}", method = RequestMethod.GET)
- public User getEmpById(@PathVariable int id) {
- return userService.getUserById(id);
- }
结果:
/emps post 添加
代码:
- @RequestMapping(path = "", method = RequestMethod.POST)
- public boolean addEmp(@RequestBody User user) {
- return userService.addUser(user);
- }
请求:
返回true
结果:
说明:参数中的json格式一定要使用标准格式,注意引号,注意Content-Type,默认的Content-Type类型是:application/x-www-form-urlencoded
因为我们使用json,则Content-Type的值应该为application/json;charset=utf-8
/emps 修改 put请求
代码:
- @RequestMapping(path = "", method = RequestMethod.PUT)
- public boolean updateEmp(@RequestBody User user) {
- return userService.editUser(user);
- }
测试:
结果:
/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 {
- @Autowired
- UserService 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(){}
- }
测试:
结果:
已删除成功,delete请求不需要正文与get请求类似
ajax传送json格式数据,关键是指定contentType,data要是json格式
如果是restful接口,把type改成对应的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) {
- //调用成功
- },
- error: function(data, textStatus, errorThrown){
- //调用失败
- }
- });
为了前端统一调用,修改后的控制器如下:
- 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 {
- @Autowired
- UserService 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?"获得数据成功!":"获得数据失败!");
- }
- @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?"获得数据成功!":"获得数据失败!");
- }
- @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(){}
- }
示例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8"/>
- <title>Title</title>
- </head>
- <body>
- <h2>员工管理</h2>
- <table border="1" width="100%" id="tabEmps">
- <tr>
- <th>编号</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": "张学友", "birthday": -41500800000, "address": "中国香港", "phone": "18989890098"},
- // "message": "获得数据成功!"
- // }
- 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>
结果:
示例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8"/>
- <title>Title</title>
- </head>
- <body>
- <h2>员工管理</h2>
- <table border="1" width="100%" id="tabEmps">
- <tr>
- <th>编号</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": "张学友", "birthday": -41500800000, "address": "中国香港", "phone": "18989890098"},
- // "message": "获得数据成功!"
- // }
- 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>
结果:
示例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8"/>
- <title>Title</title>
- </head>
- <body>
- <h2>员工管理</h2>
- <table border="1" width="100%" id="tabEmps">
- <tr>
- <th>编号</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": "张学友", "birthday": -41500800000, "address": "中国香港", "phone": "18989890098"},
- // "message": "获得数据成功!"
- // }
- 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>
结果:
示例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8"/>
- <title>Title</title>
- </head>
- <body>
- <h2>员工管理</h2>
- <table border="1" width="100%" id="tabEmps">
- <tr>
- <th>编号</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": "张学友", "birthday": -41500800000, "address": "中国香港", "phone": "18989890098"},
- // "message": "获得数据成功!"
- // }
- 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>
结果:
https://git.coding.net/zhangguo5/SpringMVC08.git
https://www.bilibili.com/video/av16991874/
5.1、请练习上课示例
5.2、请使用Spring MVC对外提供商品(Product)的管理接口,如:
product/list 获得所有商品 get
product/1 获得编号为1的商品 get
product/delete/1 删除编号为1的商品 get
product/insert 新增商品 post
product/edit 编辑商品 post
使用AJAX调用发布的服务,实现如下功能,验证、搜索、多删除功能选作。
5.3、请完成一个前后台分离的汽车管理系统(CarSystem),需要管理汽车的(车牌、颜色、价格、出厂日期、排量),要求完成CRUD功能,界面美观大方。
a)、请使用MySQL数据库创建库与表(CarSystem)
b)、使用Spring MVC定义5个RESTful服务,注意路径格式,先用fiddler测试通过。
c)、定义car.html页面,使用jQuery插件中的ajax功能消费RESTful服务实现功能,反复测试。
Fiddler2(汉化版) 链接: https://pan.baidu.com/s/1mhNTg1M 密码: qiib
来源: http://www.cnblogs.com/best/p/8006049.html