RESTful Web Services之Struts2 REST

本文介绍了RESTful Web Services的概念,REST的主要原则,以及如何利用Struts2框架创建RESTful服务。通过示例详细阐述了Struts2 REST插件的配置和方法映射,包括GET、PUT、DELETE、POST等HTTP方法,并提到了Struts2支持XML和JSON输出的配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RESTful Web Services

REST即REpresentational State Transfer,REST 是一种基于网络的软件架构约束,使用HTTP协议进行数据交换。基于REST架构的Web Services叫做RESTful Web Services。

REST的主要原则如下:

网络上的所有事物都可被抽象为资源(Resource)。
每个资源都有一个唯一的资源标识符(Resource Identifier)。
同一资源具有多种表现形式。
使用标准方法操作资源。
通过缓存来提高性能。
对资源的各种操作不会改变资源标识符。
所有的操作都是无状态的(Stateless)。

REST 架构是针对传统 Web 应用提出的一种改进,是一种新型的分布式软件设计架构。对于异构系统如何整合的问题,目前主流做法都集中在使用 SOAP、WSDL 和 WS-* 规范的 Web Services。而 REST 架构实际上也是解决异构系统整合问题的一种新思路。

现在的云服务提供支持REST的API,如OpenStack.

在这种原则下,网络上的各种资源可以有统一的命名规则,URI,人们可以通过URI来判断自己访问了什么资源,而不是只有开发人员能看懂某个方法,如user!list?page=1&pageSize=10

以下HTTP方法在RESTful Web Services里非常常用,至于具体的定义,还需看各个框架自己的设定,但大体一致。

  • Get方法, Provides a read only access to a resource

    /UserService/users 查询user的list,read only
    /UserService/users/1,查询id为1的user,read only

  • Put方法, Used to create a new resource

    /UserService/users/2,增加一位user,id=2,idempotent幂等性

  • Delete, Used to remove a resource

    /UserService/users/1,删除id为1的user,idempotent幂等性

  • Post, Used to update a existing resource or create a new resource

    /UserService/users/2,更新id为2的user

  • OPTIONS, Used to get the supported operations on a resource

    /UserService/users, 列出web services支持定义的某个list,Read Only

Struts2 REST实例

Struts2在自己的学习和做项目过程中都用过,下面以框架为例,开发一个REST架构的页面。

步骤一:建立Struts2项目,除了Struts2最基本的jar包,还需rest,convention,json-lib,xstream四个jar包
必要jar包

步骤二:配置Struts.xml,

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />
    <!-- 只想用REST 就配置这个-->
    <!-- <constant name="struts.mapper.class" value="rest" /> -->

    <!-- REST和非REST风格一起用, 就配置这个-->
    <!-- <constant name="struts.action.extension" value="xhtml,,xml,json,action"/> -->

    <!-- 以上可以不设,不论哪种,都要设定以下项目 -->
         <!-- XXXAction类后缀,可以是Controller,那么所有控制器后缀都设为Controller-->
    <constant name="struts.convention.action.suffix" value="Action" />
    <constant name="struts.convention.action.mapAllMatches" value="true" />
    <constant name="struts.convention.default.parent.package" value="rest-default" />
        <!-- Action类所在包名 -->
    <constant name="struts.convention.package.locators" value="action" />
</struts>  

步骤三:编写User.java,UserDao.java,UserService.java,注意struts2 rest插件提供的默认REST方法

目录结构


User.java

package com.rest.bean;

public class User {
    private Integer id;
    private String userName;
    private Integer age;


    public User() {
    }


    public User(Integer id, String userName, Integer age) {
        super();
        this.id = id;
        this.userName = userName;
        this.age = age;
    }


    public Integer getId() {
        return id;
    }


    public void setId(Integer id) {
        this.id = id;
    }


    public String getUserName() {
        return userName;
    }


    public void setUserName(String userName) {
        this.userName = userName;
    }


    public Integer getAge() {
        return age;
    }


    public void setAge(Integer age) {
        this.age = age;
    }

}

UserDao.java

package com.rest.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.rest.bean.User;

public class UserDao {

    private static Map<Integer,User> list =  new HashMap<Integer,User>();
    private Integer id = 6;
    // 以内存中的数据,模拟数据库的持久存储
    static {

        list.put(1,new User(1,"Tom",22));
        list.put(2,new User(2,"Josh",23));
        list.put(3,new User(3,"Luisa",18));
        list.put(4,new User(4,"John",26));
        list.put(5,new User(5,"Kate",21));
    }

    //增加或更新
    public void insert(User user) {

        if(user.getId()==null) {
            user.setId(id++);
        }

        list.put(user.getId(),user);
    }
    //删除
    public void deleteById(Integer id) {
        list.remove(id);
    }
    //查单个
    public User selectById(Integer id) {
        return list.get(id);
    }
    //查全部
    public List<User> selectUsers() {
        return new ArrayList<User>(list.values());
    }
}

UserService.java

package com.rest.service;

import java.util.List;

import com.rest.bean.User;
import com.rest.dao.UserDao;


public class UserService {

    private UserDao userDao = new UserDao();

    public void insert(User user) {
        userDao.insert(user);
    }

    public void deleteById(Integer id) {
        userDao.deleteById(id);
    }

    public User selectById(Integer id) {
        return userDao.selectById(id);
    }

    public List<User> selectUsers(){
        return userDao.selectUsers();
    }

}

以下是UserAction.java

  • 对于增加操作,固定方法为editNew,返回的jsp页面名字自己定,我的例子返回”add”,那么Struts2会映射到content的user-add.jsp。而在提交表单时的方法则是create()

  • 对于删除操作,固定方法为destory()

  • 对于修改操作,跳转页面是带参数的edit()方法,提交表单时update()

  • 对于查询操作,查全部是index(),查单个是show()

package com.rest.action;

import java.util.Collection;

import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.rest.bean.User;
import com.rest.service.UserService;

@Results( value = {
    @Result(name="success", type="redirectAction", params = {"actionName" , "user"})
})
public class UserAction extends ActionSupport implements ModelDriven<Object>{

    private static final long serialVersionUID = 1L;

    private UserService userService = new UserService();

    //id请求参数
    private Integer id;
    private User model = new User();
    private Collection<User> list;


    @Override
    public Object getModel() {
        return list != null ? list : model;
    }

    //从jsp获取id请求参数,并初始化成对应的User
    public void setId(Integer id) {
        if (id != null) {
            this.model = userService.selectById(id);
        }
        this.id = id;
    }


    /**
     * @TODO 处理不带 id 参数的 GET 查询请求,跳页面
     * @return 进入 添加用户页面  /user/new
     */
    public String editNew() {
        model = new User();
        return "add";
    }

    /**
     * @TODO 处理不带 id 参数的 POST 请求 
     * @TODO 增加用户,表单提交的action /user
     */
    public HttpHeaders create() 
    { 
        // 保存用户
        userService.insert(model); 
        addActionMessage("添加用户成功"); 
        return new DefaultHttpHeaders("success").disableCaching();
    }





    /**
    * @TODO 处理带 id 参数的 DELETE 请求,这个请求需要在jsp页面加点东西
    * @return 删除用户成功页面, /user/1
    */
    public String destroy() {
        userService.deleteById(id);
        addActionMessage("删除用户成功");
        return "success";
    } 



    /**
     * @TODO 处理带 id 参数的 GET 查询请求,负责跳页面
     * @return 进入 编辑特定用户页面 /user/2/edit
     */
    public String edit() {
        return "edit";
    }
    /**
     * @TODO 处理带 id 参数的 PUT 请求, 这个请求需要在jsp页面加点东西 
     * @return 更新用户成功页面,提交表单action /user/1
     */
    public String update() {
        userService.insert(model);
        addActionMessage("用户更新成功");
        return "success";
    }



    /**
     * @TODO 处理不带 id 参数的 GET 查询请求
     * @return 进入首页 /user, index是默认方法,不是execute了
     */
    public HttpHeaders index() {
        list = userService.selectUsers();
        //映射到WEB-INF/content/user-index.jsp上,jsp名称是  控制器-方法名
        return new DefaultHttpHeaders("index").disableCaching();
    }

    /**
     * @TODO 处理带 id 参数的 GET 查询请求,查单个user
     * @return 进入 /user/2
     */
    public HttpHeaders show() {

        return new DefaultHttpHeaders("show").setLocationId(id);
    }


}

步骤三:配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>restcase</display-name>


  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

以下是jsp页面开发
- user-index.jsp,对应index()方法,注意此处的delete方法

<body>
    <div> 信息:<s:actionmessage /> </div>
    <table>
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>年龄</th>
            <th>操作</th>
        </tr>
        <s:iterator value="model">
        <tr>
            <td><s:property value="id"/></td>
            <td><s:property value="userName"/></td>
            <td><s:property value="age"/></td>
            <td>
                <a href="user/${id}">查看show()</a>
                <a href="user/${id}/edit">修改edit()</a>
                <a href="user/${id}?_method=DELETE">删除delete()</a>
            </td>
        </tr>   
        </s:iterator>
    </table>
    <a href="user/new">添加用户editNew()</a>
</body>
  • user-show.jsp,对应show()
<body>
    <table>
        <tr>
            <th>编号</th>
            <td><s:property value="id"/></td>
        </tr>
        <tr>
            <th>名称</th>
            <td><s:property value="userName"/></td>
        </tr>
        <tr>
            <th>年龄</th>
            <td><s:property value="age"/></td>
        </tr>
    </table>
    <a href="${pageContext.request.contextPath}/user">返回</a>
</body>
  • user-edit.jsp 对应edit()
<body>
<div>修改用户,id为<s:property value="id"/></div>
    <s:form action="%{#request.contextPath}/user/%{id}" method="post">
        <!-- 注意此处加的隐藏域,表示是put请求 -->
        <s:hidden name="_method" value="put" />
        <table>
            <tr>
                <th>编号</th>
                <s:textfield name="id" disabled="true"/>
            </tr>
            <tr>
                <th>名称</th>
                <s:textfield name="userName" />
            </tr>
            <tr>
                <th>年龄</th>
                <s:textfield name="age" />
            </tr>
            <tr>
                <s:submit/>
            </tr>
        </table>
    </s:form>
<a href="${pageContext.request.contextPath}/user">返回列表</a>
</body>
  • user-add.jsp 对应editNew()
<div>增加新用户</div>
    <s:form action="%{#request.contextPath}/user" method="post">
        <table>
            <tr>
                <th>名称</th>
                <td><s:textfield name="userName"/></td>
            </tr>
            <tr>
                <th>年龄</th>
                <td><s:textfield name="age"/></td>
            </tr>
            <tr>
                <th><a href="${pageContext.request.contextPath}/user">返回列表</a></th>
                <td><s:submit value="提交"/></td>
            </tr>
        </table>
    </s:form>
</body>

测试结果
这里写图片描述
这里写图片描述
这里写图片描述

小结

对于Struts2的rest,要注意细节配置,尤其是put和delete方法。
**Struts2还能把以上的访问转变成xml或json,方便网络传输,
如访问rest/user.xml,那么需要加
xmlpull-1.1.3.1.jar包

如果访问rest/user.json,加json依赖的包

**commons-beanutils-1.8.3.jar
commons-lang-2.5.jar
commons-collections-3.1.jar
ezmorph-1.0.6.jar
json-lib-2.3-jdk15.jar**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值