ssm框架整合及Rest风格接口实现

来源:互联网 发布:js 按顺序执行 编辑:程序博客网 时间:2024/06/05 07:33

1.前言

SSM框架整合即Spring+SpringMVC+Mybatis三大框架进行整合。属于现在Java项目主流的框架选择。
关于这三大框架的介绍,本篇幅不做说明。项目中结合了Maven的使用。
关于Eclipse构建Maven项目详情文章:
http://blog.csdn.net/it_faquir/article/details/54562242
目录结构:
这里写图片描述

2.Maven依赖

首先创建一个Maven的Web项目。这里将其命名为“SSMIntegration”及SMM整合。

通过Maven的pom.xml加入各所需jar包。

<properties>        <spring-version>4.3.5.RELEASE</spring-version>    </properties>    <dependencies>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>            <scope>test</scope>        </dependency>        <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>servlet-api</artifactId>            <version>2.5</version>        </dependency>        <!-- spring & mvc start -->        <!-- http://projects.spring.io/spring-framework/ -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>${spring-version}</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>${spring-version}</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-test</artifactId>            <version>${spring-version}</version>        </dependency>        <!-- datasource 必须 -->        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-jdbc</artifactId>            <version>${spring-version}</version>        </dependency>        <!-- spring & mvc end -->        <!-- mybaits start -->        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis</artifactId>            <version>3.4.1</version>        </dependency>        <!-- spring 整合mybatis必备 -->        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis-spring</artifactId>            <version>1.3.0</version>        </dependency>        <!-- mybatis end -->        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.0.26</version>        </dependency>        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>6.0.5</version>        </dependency>        <!-- 使用@RequestBody @ResponseBody 时得用到下面两jar包 -->        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-core</artifactId>            <version>2.8.5</version>        </dependency>        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>            <version>2.8.5</version>        </dependency>    </dependencies>

上面加入了Spring/SpringMVC/Mybatis及其它所需的依赖,其中jackson-core和jackson-databind千万别忘了,否则你会发现Spring无法解析传来json数据,具体请看注释。

3.各种配置

web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns="http://java.sun.com/xml/ns/javaee"    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"    version="2.5">    <display-name>SSHIntergration</display-name>    <welcome-file-list>        <welcome-file>index.jsp</welcome-file>    </welcome-file-list>    <!-- needed for ContextLoaderListener -->    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:applicationContext.xml</param-value>    </context-param>    <!-- Bootstraps the root web application context before servlet initialization -->    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <!-- SpringMVC servlet -->    <servlet>        <servlet-name>springDispatcherServlet</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <init-param>            <param-name>contextConfigLocation</param-name>            <param-value>classpath:applicationContext-web.xml</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>springDispatcherServlet</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping>    <!-- 防止乱码 -->    <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>    <!-- 用来过滤rest中的方法,在隐藏域中的put/delete方式,注意 由于执行顺序原因  一定要放在编码过滤器下面,否则会出现编码问题 -->    <filter>        <filter-name>HiddenHttpMethodFilter</filter-name>        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>        <init-param>            <param-name>methodParam</param-name>            <param-value>_method</param-value>        </init-param>    </filter>    <filter-mapping>        <filter-name>HiddenHttpMethodFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping></web-app>

需要注意:
1.html不支持put、delete的方式,但Spring mvc 支持REST风格的请求方法,GET、POST、PUT和DELETE四种请求方法分别代表了数据库CRUD中的select、insert、update、delete。因此想要实现四种请求,需要在表单中使用隐藏域,并在web.xml中配置HiddenHttpMethodFilter过滤器。
2.为了防止乱码,因此需要通过CharacterEncodingFilter实现全局编码过滤。注意一点要放在web.xml内容中的其它过滤器上方,否则由于执行顺序原因,导致依然出现乱码问题,具体原因需进一步探讨。

做好基本的准备之后,接下来进行具体的代码编写

在根目录下创建
applicationContext-web.xml | SpringMVC配置文件
applicationContext.xml | Spring配置文件
jdbc.properties | jdbc配置文件
mybatis.cfg.xml | mybatis的配置文件
在web.xml中SpringDispatcherServlet指定SpringMVC的配置位置,contextConfigLocation指定Spring的配置位置。四个文件其具体内容如下,详情请看到代码中的注解。

applicationContext-web.xml :

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc"    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">    <context:component-scan base-package="priv.hgs.ssm.controller" >        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan>    <!--配置只要解析器-->    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name="prefix" value="/WEB-INF/"/>        <property name="suffix" value=".jsp"/>    </bean>    <mvc:annotation-driven/></beans>

applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"    xmlns:c="http://www.springframework.org/schema/c"    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">    <context:component-scan base-package="priv.hgs.ssm">        <context:exclude-filter type="annotation"            expression="org.springframework.stereotype.Controller" />    </context:component-scan>    <!-- 加载配置文件 -->    <bean        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <property name="location" value="classpath:jdbc.properties"></property>    </bean>    <!-- 配置数据源 -->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"        init-method="init" destroy-method="close">        <property name="driverClassName" value="${jdbc.driver}" />        <property name="url" value="${jdbc.url}" />        <property name="username" value="${jdbc.username}" />        <property name="password" value="${jdbc.password}" />        <!-- 初始化连接大小 -->        <property name="initialSize" value="${initialSize}"></property>        <!-- 同一时间连接池最大数量 0则无限制 -->        <property name="maxActive" value="${maxActive}"></property>        <!-- 连接池最大空闲 池里不会被释放的最多空闲连接数 0则无限制 -->        <property name="maxIdle" value="${maxIdle}"></property>        <!-- 连接池最小空闲 在不创建新连接的情况下,池中保持空闲的最小连接数 -->        <property name="minIdle" value="${minIdle}"></property>        <!-- 获取连接最大等待时间 -->        <property name="maxWait" value="${maxWait}"></property>    </bean>    <!-- DAO接口所在包名,Spring会自动查找其下的类,,这里通过配置文件的方式 -->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        <property name="dataSource" ref="dataSource" />        <!-- 添加mybatis的配置文件,如果没有可以不添加 -->        <property name="configLocation" value="classpath:mybatis.cfg.xml"></property>    </bean>    <bean class="org.mybatis.spring.SqlSessionTemplate"        c:sqlSessionFactory-ref="sqlSessionFactory">    </bean></beans>

jdbc.properties:

jdbc.driver=com.mysql.cj.jdbc.Driver#定义连接的URL地址,设置编码集,时间域,允许多条SQL语句操作œjdbc.url=jdbc:mysql://localhost:3306/dbtest?characterEncoding=utf-8&serverTimezone=UTC&allowMultiQueries=truejdbc.username=rootjdbc.password=asd123asd#jdbc.password=StrLDvcH92s8tsn3#定义初始连接数initialSize=0#定义最大连接数maxActive=20#定义最大空闲maxIdle=20#定义最小空闲minIdle=1#定义最长等待时间maxWait=30000

4.相关数据表

本次测试使用到了MySQL数据库,在数据库中创建了两种表,分别为student表、score表,其SQL如下:
student表

CREATE TABLE `student` (  `id` int(12) NOT NULL AUTO_INCREMENT,  `name` varchar(32) NOT NULL,  `password` varchar(32) NOT NULL,  `gender` int(2) NOT NULL DEFAULT '1' COMMENT '0-女;1-男',  `grate` varchar(32) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

score表

CREATE TABLE `score` (  `scid` int(11) NOT NULL,  `course` varchar(10) NOT NULL,  `score` int(3) unsigned zerofill NOT NULL,  `stid` int(11) NOT NULL,  PRIMARY KEY (`scid`),  KEY `stukey` (`stid`),  CONSTRAINT `stukey` FOREIGN KEY (`stid`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在上面两种表中,需要注意的是,score的scid设置了外键为student表中的id,并且设置了级联删除和级联更新。

5.MyBatis上场

一切就绪,java代码该上场了。
首先针对以上两张表在domain包下创建两个javaBean。
Student.java

public class Student {    private int stid;    private String name;    private String password;    private int gender;    private String grate;    private List<Score> scores;// 一对多        get/set...        toString...}

Score.java

public class Score {    private int id;    private int stid;    private String course;    private int score;    get/set...    toString...}

编写mapper文件
在mapping包下创建一个SSMHelloMapper.xml的关系映射文件
我这里,分别列出了增删改查的示例,代码如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="priv.hgs.ssm.dao.IHelloDao">    <resultMap type="Student" id="Stu">        <id property="stid" column="id" />        <result property="name" column="name" />        <result property="password" column="password" />        <result property="genter" column="genter" />        <result property="grate" column="grate" />        <!-- 一对多关系设置,集合 .注意 两个表的id最好不要一样,否则只能查到一条数据,也可以通过别名解决 -->        <collection property="scores" ofType="Score">            <id column="scid" property="id" />            <result property="course" column="course" />            <result property="score" column="score" />            <result property="stid" column="stid" />        </collection>    </resultMap>    <!-- 对于数据表与实体类属性不一致情况,使用resultMap进行处理 -->    <!--这里不适合使用内连接的方式,即 SELECT st.*,sc.* FROM student st,Score sc WHERE st.id         = #{id} and st.id = sc.sid; 因为:当score没有对应值时,将查不出信息。 所有:最好使用左连接 -->    <select id="getStuById" resultMap="Stu">        SELECT st.*,sc.* FROM student        st LEFT JOIN score sc ON st.id = sc.stid WHERE st.id=#{id};    </select>    <delete id="delStuById">        DELETE FROM student WHERE id = #{stid};    </delete>    <update id="updateStu" parameterType="Map">        UPDATE student        <set>            <if test="password != null">                password = #{password},            </if>            <if test="grate != null">                grate = #{grate}            </if>        </set>        where id = #{stid};    </update>    <insert id="insetStu" parameterType="Student">        INSERT INTO        student(name,password,gender,grate)        VALUES(#{name},#{password},#{gender},#{grate});    </insert></mapper>

在查询中,演示了左连接的查询方式,由于用内连接有可能对应的数据,在score表中不存在的情况,引起异常。

6.dao的编写

dao层

public interface IHelloDao {    // 对于其参数名与mapper中不一致情况,可适应@Param("名称") 注解进行校正    Student getStuById(@Param("id") int stid);    int delStuById(int stid);    int updateStu(Map param);    int insetStu(Student student);}

注意:接口名一定要与映射文件中的各id的名字一样,否则MyBatis无法识别,从而实现半自动化。
dao imp

@Componentpublic class HelloDao implements IHelloDao {    @Autowired    SqlSessionTemplate ssTemplate;    @Override    public Student getStuById(int stid) {        return ssTemplate.getMapper(IHelloDao.class).getStuById(stid);    }    @Override    public int delStuById(int stid) {        return ssTemplate.getMapper(IHelloDao.class).delStuById(stid);    }    @Override    public int updateStu(Map param) {        return ssTemplate.getMapper(IHelloDao.class).updateStu(param);    }    @Override    public int insetStu(Student student) {        return ssTemplate.getMapper(IHelloDao.class).insetStu(student);    }}

这里使用了SpringData的模板,SqlSessionTemplate也就是Spring配置文件中所配的,如下:

<!-- DAO接口所在包名,Spring会自动查找其下的类,,这里通过配置文件的方式 -->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        <property name="dataSource" ref="dataSource" />        <!-- 添加mybatis的配置文件,如果没有可以不添加 -->        <property name="configLocation" value="classpath:mybatis.cfg.xml"></property>    </bean>

通过SqlSessionTemplate,可以让我们很轻松的实现增删改查。
Spring 常用数据库模板
模板类 用途
|jdbc.core.JdbcTemplate | jdbc连接 |

|com.hibernate3.HibernateTemplate
(org.springframework.orm.hibernate5.HibernateTemplate最新) |
Hibernate 3.x以上的Session |

|org.mybatis.spring.SqlSessionTemplate | Mybatis模板 |

|org.springframework.data.redis.core.StringRedisTemplate |Redis |

|org.springframework.data.mongodb.core.MongoTemplate |Mongodb |

|orm.jdo.JdoTemplate |Java数据对象(Java Data Object) 实现 |

|orm.jpa.JpaTemplate |Java持久化API的实体管理器 |

到了这一步,可以说已经完成了大部分工作,我们来测试下所写的代码正不正确。

7.Dao的junit测试

创建一个HelloTest类用于我们的单元测试

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext.xml"})public class HelloTest {    @Autowired    IHelloDao helloDao;    @Test    public void testQueryStu(){        Student stu = helloDao.getStuById(1);        System.out.println(stu);    }    @Test    public void testDelStu(){        int result = helloDao.delStuById(2);        System.out.println(result);    }    @Test    public void testUpdateStu(){        Map<String,String> param = new HashMap<>();        param.put("stid","1");        param.put("password", "asd");        int result = helloDao.updateStu(param);        System.out.println(result);    }    @Test    public void testInsertStu(){        Student stu = new Student();        stu.setName("魔女");        stu.setGender(0);        stu.setPassword("asd123asd");        stu.setGrate("八年二班");        int result = helloDao.insetStu(stu);        System.out.println(result);    }}

测试模块实现了对增删改查操作的测试。
如果测试成功,数据库中的数据将会发生变化,如果没变化,请检查代码是否有误。

注意:该测试类需要junit和spring-test相关依赖。

8.Service的编写

web的实现
对dao层的实现基本OK,接着需要实现service层,及controller的实现。
service层和dao层差不多,就是在dao的基础上套了一层。
IHelloService接口:

public interface IHelloService {    // 对于其参数名与mapper中不一致情况,可适应@Param("名称") 注解进行校正    Student getStuById(@Param("id") int stid);    int delStuById(int stid);    int updateStu(Map param);    int insetStu(Student student);}

实现类HelloService:

@Servicepublic class HelloService implements IHelloService {    @Autowired    IHelloDao helloDao;    @Override    public Student getStuById(int stid) {        return helloDao.getStuById(stid);    }    @Override    public int delStuById(int stid) {        return helloDao.delStuById(stid);    }    @Override    public int updateStu(Map param) {        return helloDao.updateStu(param);    }    @Override    public int insetStu(Student student) {        return helloDao.insetStu(student);    }}
注意:这里要用@Service注解用于标注业务层组件(以上我说的dao层和service层,只是为了个人表述方便而起的)。

9.Controller对Rest的实现

控制器:

@RequestMapping(value = "/student")@RestControllerpublic class HelloControler {    @Autowired    IHelloService helloService;    @RequestMapping(value = "/{stid}", method = RequestMethod.GET)    public Student getStudentById(@PathVariable int stid) {        Student student = helloService.getStuById(stid);        if (student == null) {            student = new Student();        }        return student;    }    @RequestMapping(value = "/{stid}", method = RequestMethod.DELETE)    public Result delStuById(@PathVariable int stid) {        int r = helloService.delStuById(stid);        if (r == 0)            return new Result(403, "删除失败");        return new Result(200, "删除操作成功");    }    @RequestMapping(value = "/addStu", method = RequestMethod.POST)    public Result addAStu(Student student) {        int result = helloService.insetStu(student);        if (result == 0)            return new Result(403, "添加失败。");        return new Result(200, "添加成功。");    }    @RequestMapping(value="/updateStu",method = RequestMethod.PUT)    public Result updateStu(Student student){        System.out.println(student);        Map<String,String> param = new HashMap<>();        param.put("stid", ""+student.getStid());        param.put("password", student.getPassword());        param.put("grate", student.getGrate());        int result = helloService.updateStu(param);        if (result == 0)            return new Result(403, "更新失败。");        return new Result(200, "更新成功。");    }}

注意:

1.该控制器使用了@RestController 而不是@Controller,这样我们可以偷懒,从而轻松实现REST,而不必为实现将对象转为Json数据而在每个Mapping上添加@ResponseBody。
**2.**Result对象为了方便而编写的一个POJO

public class Result {    private int stateCode;    private String message;    public Result() {        super();    }    public Result(int stateCode, String message) {        super();        this.stateCode = stateCode;        this.message = message;    }    get/set...    toString..}

3.你会发现在控制器中适应了PUT、DELETE两个请求方法,用于更新和删除操作,对应SpringMVC来说,这是支持的。但是对于HTML的表单提交只支持POST和GET两种方式。(REST的关键原则之一就是“使用标准接口”(the use of the Uniform Interface),也就是提倡根据不同的语义使用GET, PUT, POST和DELETE方法)。
那么该如何实现对PUT和DELETE的支持呢?(web.xml的配置请往前翻)
在表单这边,需要使用隐藏域的方式,请详看页面代码
index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <!-- 其中get和post方法是html中自带的,但是不支持PUT和DELETE方法,所以需要通过POST方法模拟这两种方法,只需要在表单中添加一个隐藏域,名为_method,值为PUT或DELETE。 -->    <form action="student/updateStu" method="POST">    <input type="hidden" name="_method" value="PUT">        <input type="hidden" name="stid" value="1" />         密码:<input type="text" name="password" /> <span>         班级:<input type="text" name="grate" />            <input type="submit" value="修改" />    </form>    <form action="student/addStu" method="post">    name:<input type="text" name="name" /> <br/>password:<input type="text" name="password" /> <br/>   grate:<input type="text" name="grate" /> <br/>  gender:<input type="text" name="gender"/> <br/>         <input type="submit" value="添加" />    </form>    <form action="student/1" method="post">        <input type="hidden" name="_method" value="DELETE"/>        <input type="submit" value="删除" />    </form></body></html>

注意代码段

<input type="hidden" name="_method" value="PUT">

隐藏中name使用了”_method”,与web.xml所配置的对应过滤器param-value保持一致。

<filter>        <filter-name>HiddenHttpMethodFilter</filter-name>        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>        <init-param>            <param-name>methodParam</param-name>            <param-value>_method</param-value>        </init-param>    </filter>

10.Rest功能测试

到此为止,代码部分完全结束了。我们来看看效果。这个结果还是很有必要给出的。
运行,部署到服务器之后可看到如下效果页
http://localhost:8080/SSMIntegration/
这里写图片描述

1.添加操作
填入对应值,如玛丽、123123、九年一班、0 (这里0代表女)
添加成功,在页面中将会返回
{“stateCode”:200,”message”:”添加成功。”}
在数据库中也将会多出一条添加的数据
这里写图片描述

2.查询
http://localhost:8080/SSMIntegration/student/1
返回结果:
{“stid”:1,”name”:”玛丽”,”password”:”123123”,”gender”:0,”grate”:”九年一班”,”score”:[]}

3.修改
为了测试方便,在表单中,加stid设置了默认值1,也就是只对stid为1的数据进行修改。
输入修改的数据如:asd、计算机科学与技术
{“stateCode”:200,”message”:”更新成功。”}
这里写图片描述

4.删除
同样为了操作方便,将stid设置成了1,点击删除:
{“stateCode”:200,”message”:”删除操作成功”}
此查看数据库,会发现数据已经没有了。再次删除将会出现错误
{“stateCode”:403,”message”:”删除失败”}

11.结束

OK,基本上完成了。总算结束了,累死我了。。。
可以试着,模仿敲一敲。如有疑问请留言。
小弟的博客专栏:http://blog.csdn.net/IT_faquir/article/list/

阅读全文
2 0
原创粉丝点击