CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

轻量级java ee企业应用实战 百度云(难以置信)轻量级javaee企业应用实战pdf下载,一个用Java实现的超轻量级RESTful Web服务示例,

1.轻量级java ee企业应用实战 百度云

通过管理一套图书的完整代码示例,来探索轻量级的 RESTful 服务• 来源:linux.cn • 作者:Marty Kalin • 译者:MCGA •(本文字数:24337,阅读时长大约:28 分钟)。

2.java ee企业级应用开发教程百度云

Web 服务,以这样或那样的形式,已经存在了近二十年比如, XML-RPC 服务 出现在 90 年代后期,紧接着是用 SOAP 分支编写的服务在 XML-RPC 和 SOAP 这两个开拓者之后出现后不久,REST 架构风格的服务在大约 20 年前也出现了。

3.轻量级javaee企业应用实战pdf下载

REST 风格(以下简称 Restful)服务现在主导了流行的网站,比如 eBay、Facebook 和 Twitter尽管分布式计算的 Web 服务有很多替代品(如 Web 套接字、微服务和远程过程调用的新框架),但基于 Restful 的 Web 服务依然具有吸引力,原因如下:。

4.Java EE(SSM)企业应用实战

Restful 服务建立在现有的基础设施和协议上,特别是 Web 服务器和 HTTP/HTTPS 协议一个拥有基于 HTML 的网站的组织可以很容易地为客户添加 Web 服务,这些客户对数据和底层功能更感兴趣,而不是对 HTML 的表现形式感兴趣。

5.java ee企业级应用开发教程电子版

比如,亚马逊就率先通过网站和 Web 服务(基于 SOAP 或 Restful)提供相同的信息和功能Restful 服务将 HTTP 当作 API,因此避免了复杂的软件分层,这种分层是基于 SOAP 的 Web 服务的明显特征。

6.java ee企业级应用开发教程

比如,Restful API 支持通过 HTTP 命令(POST-GET-PUT-DELETE)进行标准的 CRUD(增加-读取-更新-删除)操作;通过 HTTP 状态码可以知道请求是否成功或者为什么失败。

7.java ee企业级应用开发

Restful Web 服务可以根据需要变得简单或复杂Restful 是一种风格,实际上是一种非常灵活的风格,而不是一套关于如何设计和构造服务的规定(伴随而来的缺点是,可能很难确定哪些服务不能算作 Restful 服务。

)作为使用者或者客户端,Restful Web 服务与语言和平台无关客户端发送 HTTP(S) 请求,并以适合现代数据交换的格式(如 JSON)接收文本响应几乎每一种通用编程语言都至少对 HTTP/HTTPS 有足够的(通常是强大的)支持,这意味着 Web 服务的客户端可以用这些语言来编写。

这篇文章将通过一段完整的 Java 代码示例来探讨轻量级的 Restful 服务基于 Restful 的“小说” Web 服务基于 Restful 的“小说” web 服务包含三个程序员定义的类:Novel 类代表一个小说,只有三个属性:机器生成的 ID、作者和标题。

属性可以根据实际情况进行扩展,但我还是想让这个例子看上去更简单一些Novels 类包含了用于各种任务的工具类:将一个 Novel 或者它们的列表的纯文本编码转换成 XML 或者 JSON;支持在小说集合上进行 CRUD 操作;以及从存储在文件中的数据初始化集合。

Novels 类在 Novel 实例和 servlet 之间起中介作用NovelsServlet 类是从 HttpServlet 中继承的,HttpServlet 是一段健壮且灵活的代码,自 90 年代末的早期企业级 Java 就已经存在了。

对于客户端的 CRUD 请求,servlet 可以当作 HTTP 的端点 servlet 代码主要用于处理客户端的请求和生成相应的响应,而将复杂的细节留给 Novels 类中的工具类进行处理一些 Java 框架,比如 Jersey(JAX-RS)和 Restlet,就是为 Restful 服务设计的。

尽管如此,HttpServlet 本身为完成这些服务提供了轻量、灵活、强大且充分测试过的 API我会通过下面的“小说”例子来说明部署“小说” Web 服务当然,部署“小说” Web 服务需要一个 Web 服务器。

我的选择是 Tomcat ,但是如果该服务托管在 Jetty 或者甚至是 Java 应用服务器上,那么这个服务应该至少可以工作(著名的最后一句话!) 在我的网站上 有总结了如何安装 Tomcat 的 README 文件和代码。

还有一个附带文档的 Apache Ant 脚本,可以用来构建“小说”服务(或者任何其他服务或网站),并且将它部署在 Tomcat 或相同的服务Tomcat 可以从它的 官网 上下载当你在本地安装后,将 TOMCAT_HOME 设置为安装目录。

有两个子目录值得关注:TOMCAT_HOME/bin 目录包含了类 Unix 系统(startup.sh 和 shutdown.sh)和 Windows(startup.bat 和 shutdown.bat) 的启动和停止脚本。

Tomcat 作为 Java 应用程序运行Web 服务器的 servlet 容器叫做 Catalina(在 Jetty 中,Web 服务器和容器的名字一样)当 Tomcat 启动后,在浏览器中输入 http://localhost:8080/可以查看详细文档,包括示例。

TOMCAT_HOME/webapps 目录是已部署的 Web 网站和服务的默认目录部署网站或 Web 服务的直接方法是复制以 .war 结尾的 JAR 文件(也就是 WAR 文件)到 TOMCAT_HOME/webapps 或它的子目录下。

然后 Tomcat 会将 WAR 文件解压到它自己的目录下比如,Tomcat 会将 novels.war 文件解压到一个叫做 novels 的子目录下,并且保留 novels.war 文件一个网站或 Web 服务可以通过删除 WAR 文件进行移除,也可以用一个新版 WAR 文件来覆盖已有文件进行更新。

顺便说一下,调试网站或服务的第一步就是检查 Tomcat 已经正确解压 WAR 文件;如果没有的话,网站或服务就无法发布,因为代码或配置中有致命错误因为 Tomcat 默认会监听 8080 端口上的 HTTP 请求,所以本机上的 URL 请求以 http://localhost:8080/ 开始。

通过添加不带 .war 后缀的 WAR 文件名来访问由程序员部署的 WAR 文件:http://locahost:8080/novels/如果服务部署在 TOMCAT_HOME 下的一个子目录中(比如,myapps),这会在 URL 中反映出来:

http://locahost:8080/myapps/novels/我会在靠近文章结尾处的测试部分提供这部分的更多细节如前所述,我的主页上有一个包含 Ant 脚本的 ZIP 文件,这个文件可以编译并且部署网站或者服务。

(这个 ZIP 文件中也包含一个 novels.war 的副本)对于“小说”这个例子,命令的示例(% 是命令行提示符)如下:% ant -Dwar.name=novels deploy这个命令首先会编译 Java 源代码,并且创建一个可部署的 novels.war 文件,然后将这个文件保存在当前目录中,再复制到 TOMCAT_HOME/webapps 目录中。

如果一切顺利,GET 请求(使用浏览器或者命令行工具,比如 curl)可以用来做一个测试:% curl http://localhost:8080/novels/默认情况下,Tomcat 设置为 热部署(hot deploys)

:Web 服务器不需要关闭就可以进行部署、更新或者移除一个 web 应用“小说”服务的代码让我们回到“小说”这个例子,不过是在代码层面考虑下面的 Novel 类:例 1:Novel 类package novels;

import java.io.Serializable; publicclassNovelimplementsSerializable, Comparable { staticfinal

long serialVersionUID = 1L; private String author; private String title; privateint id;

publicNovel(){ } publicvoidsetAuthor(final String author){ this.author = author; } public String

getAuthor(){ returnthis.author; } publicvoidsetTitle(final String title){ this.title = title; }

public String getTitle(){ returnthis.title; } publicvoidsetId(finalint id){ this.id = id; } public

intgetId(){ returnthis.id; } publicintcompareTo(final Novel other){ returnthis.id – other.id; } }

这个类实现了 Comparable 接口中的 compareTo 方法,因为 Novel 实例是存储在一个线程安全的无序 ConcurrentHashMap 中在响应查看集合的请求时,“小说”服务会对从映射中提取的集合(一个 ArrayList)进行排序;compareTo 的实现通过 Novel 的 ID 将它按升序排序。

Novels 类中包含多个实用工具函数:例 2:Novels 实用工具类package novels; import java.io.IOException; import java.io.File;

import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import

java.io.BufferedReader; import java.nio.file.Files; import java.util.stream.Stream; import java.util.concurrent.ConcurrentMap;

import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import

java.util.Collections; import java.beans.XMLEncoder; import javax.servlet.ServletContext; // not in JavaSE

import org.json.JSONObject; import org.json.XML; publicclassNovels{ privatefinal String fileName =

“/WEB-INF/data/novels.db”; private ConcurrentMap novels; private ServletContext sctx;

private AtomicInteger mapKey; publicNovels(){ novels = new ConcurrentHashMap(); mapKey =

new AtomicInteger(); } publicvoidsetServletContext(ServletContext sctx){ this.sctx = sctx; }

public ServletContext getServletContext(){ returnthis.sctx; } public ConcurrentMap

getConcurrentMap(){ if (getServletContext() == null) returnnull; // not initializedif (novels.size() <

1) populate(); returnthis.novels; } public String toXml(Object obj){ // default encoding

String xml = null; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); XMLEncoder encoder =

new XMLEncoder(out); encoder.writeObject(obj); encoder.close(); xml = out.toString(); }

catch(Exception e) { } return xml; } public String toJson(String xml){ // option for requester

try { JSONObject jobt = XML.toJSONObject(xml); return jobt.toString(3); // 3 is indentation level

} catch(Exception e) { } returnnull; } publicintaddNovel(Novel novel)

{ int id = mapKey.incrementAndGet(); novel.setId(id); novels.put(id, novel);

return id; } privatevoidpopulate(){ InputStream in = sctx.getResourceAsStream(this.fileName);

// Convert novel.db string data into novels.if (in != null) { try { InputStreamReader isr =

new InputStreamReader(in); BufferedReader reader = new BufferedReader(isr); String record =

null; while ((record = reader.readLine()) != null) { String[] parts = record.split(

“!”); if (parts.length == 2) { Novel novel = new Novel(); novel.setAuthor(parts[

0]); novel.setTitle(parts[1]); addNovel(novel); // sets the Id, adds to map

} } in.close(); } catch (IOException e) { } } } }

最复杂的方法是 populate,这个方法从一个包含在 WAR 文件中的文本文件读取这个文本文件包括了“小说”的初始集合要打开此文件,populate 方法需要 ServletContext,这是一个 Java 映射类型,包含了关于嵌入在 servlet 容器中的 servlet 的所有关键信息。

这个文本文件有包含了像下面这样的记录:Jane Austen!Persuasion 这一行被解析为两部分(作者和标题),由感叹号(!)分隔然后这个方法创建一个 Novel 实例,设置作者和标题属性,并且将“小说”加到容器中,保存在内存中。

Novels 类也有一些实用工具函数,可以将“小说”容器编码为 XML 或 JSON,取决于发出请求的人所要求的格式默认是 XML 格式,但是也可以请求 JSON 格式一个轻量级的 XML 转 JSON 包提供了 JSON。

下面是关于编码的更多细节例 3:NovelsServlet 类package novels; import java.util.concurrent.ConcurrentMap; import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import java.util.Arrays; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import

java.io.OutputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.beans.XMLEncoder;

import org.json.JSONObject; import org.json.XML; publicclass NovelsServlet extends HttpServlet {

static final long serialVersionUID = 1L; private Novels novels; // back-end bean// Executed when servlet is first loaded into container.

@Overridepublicvoid init() { this.novels = new Novels(); novels.setServletContext(this

.getServletContext()); } // GET /novels// GET /novels?id=1@Overridepublicvoid doGet(HttpServletRequest request, HttpServletResponse response) {

String param = request.getParameter(“id”); Integer key = (param == null) ? null : Integer.valueOf((param.trim()));

// Check user preference for XML or JSON by inspecting// the HTTP headers for the Accept key.boolean json =

false; String accept = request.getHeader(“accept”); if (accept != null && accept.contains(

“json”)) json = true; // If no query string, assume client wants the full list.if (key == null

) { ConcurrentMap map = novels.getConcurrentMap(); Object list = map.values().toArray(); Arrays.sort(list);

String payload = novels.toXml(list); // defaults to Xmlif (json) payload = novels.toJson(payload);

// Json preferred? sendResponse(response, payload); } // Otherwise, return the specified Novel.

else { Novel novel = novels.getConcurrentMap().get(key); if (novel == null) {

// no such NovelString msg = key + ” does not map to a novel.\n”; sendResponse(response, novels.toXml(msg)); }

else { // requested Novel foundif (json) sendResponse(response, novels.toJson(novels.toXml(novel)));

else sendResponse(response, novels.toXml(novel)); } } } // POST /novels@Override

publicvoid doPost(HttpServletRequest request, HttpServletResponse response) { String author = request.getParameter(

“author”); String title = request.getParameter(“title”); // Are the data to create a new novel present?

if (author == null || title == null) thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST));

// Create a novel. Novel n = new Novel(); n.setAuthor(author); n.setTitle(title);

// Save the ID of the newly created Novel. int id = novels.addNovel(n); // Generate the confirmation message.

String msg = “Novel ” + id + ” created.\n”; sendResponse(response, novels.toXml(msg)); }

// PUT /novels@Overridepublicvoid doPut(HttpServletRequest request, HttpServletResponse response) {

/* A workaround is necessary for a PUT request because Tomcat does not generate a workable parameter map for the PUT verb. */

String key = null; String rest = null; boolean author = false; /* Let the hack begin. */

try { BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));

String data = br.readLine(); /* To simplify the hack, assume that the PUT request has exactly two parameters: the id and either author or title. Assume, further, that the id comes first. From the client side, a hash character # separates the id and the author/title, e.g., id=33#title=War and Peace */

String[] args = data.split(“#”); // id in args[0], rest in args[1]String[] parts1 = args[0].split(

“=”); // id = parts1[1] key = parts1[1]; String[] parts2 = args[1].split(“=”

); // parts2[0] is keyif (parts2[0].contains(“author”)) author = true; rest = parts2[1]; }

catch(Exception e) { thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); }

// If no key, then the request is ill formed.if (key == null) thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST));

// Look up the specified novel. Novel p = novels.getConcurrentMap().get(Integer.valueOf((key.trim())));

if (p == null) { // not foundString msg = key + ” does not map to a novel.\n”; sendResponse(response, novels.toXml(msg)); }

else { // foundif (rest == null) { thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST)); }

// Do the editing.else { if (author) p.setAuthor(rest); else p.setTitle(rest);

String msg = “Novel ” + key + ” has been edited.\n”; sendResponse(response, novels.toXml(msg)); } } }

// DELETE /novels?id=1@Overridepublicvoid doDelete(HttpServletRequest request, HttpServletResponse response) {

String param = request.getParameter(“id”); Integer key = (param == null) ? null : Integer.valueOf((param.trim()));

// Only one Novel can be deleted at a time.if (key == null) thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST));

try { novels.getConcurrentMap().remove(key); String msg = “Novel ” + key + ” removed.\n”

; sendResponse(response, novels.toXml(msg)); } catch(Exception e) {

thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); } }

// Methods Not Allowed@Overridepublicvoid doTrace(HttpServletRequest request, HttpServletResponse response) {

thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_METHOD_NOT_ALLOWED)); } @Override

publicvoid doHead(HttpServletRequest request, HttpServletResponse response) { thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_METHOD_NOT_ALLOWED)); }

@Overridepublicvoid doOptions(HttpServletRequest request, HttpServletResponse response) { throw

new RuntimeException(Integer.toString(HttpServletResponse.SC_METHOD_NOT_ALLOWED)); } // Send the response payload (Xml or Json) to the client.

privatevoid sendResponse(HttpServletResponse response, String payload) { try { OutputStream out = response.getOutputStream(); out.write(payload.getBytes()); out.flush(); }

catch(Exception e) { thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); } } }

上面的 NovelsServlet 类继承了 HttpServlet 类,HttpServlet 类继承了 GenericServlet 类,后者实现了 Servlet 接口:NovelsServlet

extends HttpServlet extends GenericServlet implements Servlet 从名字可以很清楚的看出来,HttpServlet 是为实现 HTTP(S) 上的 servlet 设计的。

这个类提供了以标准 HTTP 请求动词(官方说法, 方法(methods))命名的空方法:doPost (Post = 创建)doGet (Get = 读取)doPut (Put = 更新)doDelete (Delete = 删除)

其他一些 HTTP 动词也会涉及到HttpServlet 的子类,比如 NovelsServlet,会重载相关的 do 方法,并且保留其他方法为 空(no-ops)NovelsServlet 重载了七个 do 方法。

每个 HttpServlet 的 CRUD 方法都有两个相同的参数下面以 doPost 为例:publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)。

{ request 参数是一个 HTTP 请求信息的映射,而 response 提供了一个返回给请求者的输出流像 doPost 的方法,结构如下:读取 request 信息,采取任何适当的措施生成一个响应。

如果该信息丢失或者损坏了,就会生成一个错误使用提取的请求信息来执行适当的 CRUD 操作(在本例中,创建一个 Novel),然后使用 response 输出流为请求者编码一个适当的响应在 doPost 例子中,响应就是已经成功生成一个新“小说”并且添加到容器中的一个确认。

当响应被发送后,输出流就关闭了,同时也将连接关闭了关于方法重载的更多内容HTTP 请求的格式相对比较简单下面是一个非常熟悉的 HTTP 1.1 的格式,注释由双井号分隔:GET /novels              。

## start line Host: localhost:8080## header element Accept-type: text/plain  ## ditto … [body]                  

## POST and PUT only第一行由 HTTP 动词(在本例中是 GET)和以名词(在本例中是 novels)命名目标资源的 URI 开始报头中包含键-值对,用冒号分隔左面的键和右面的值报头中的键 Host(大小写敏感)是必须的;主机名 localhost 是当前机器上的本地符号地址,8080 端口是 Tomcat web 服务器上等待 HTTP 请求的默认端口。

(默认情况下,Tomcat 在 8443 端口上监听 HTTP 请求)报头元素可以以任意顺序出现在这个例子中,Accept-type 报头的值是 MIME 类型 text/plain一些请求(特别是 POST 和 PUT)会有报文,而其他请求(特别是 GET 和 DELETE)没有。

如果有报文(可能为空),以两个换行符将报头和报文分隔开;HTTP 报文包含一系列键-值对对于无报文的请求,比如说查询字符串,报头元素就可以用来发送信息下面是一个用 ID 2 对 /novels 资源的 GET 请求:。

GET /novels?id=2通常来说,查询字符串以问号开始,并且包含一个键-值对,尽管这个键-值可能值为空带有 getParameter 和 getParameterMap 等方法的 HttpServlet 很好地回避了有报文和没有报文的 HTTP 请求之前的差异。

在“小说”例子中,getParameter 方法用来从 GET、POST 和 DELETE 方法中提取所需的信息(处理 PUT请求需要更底层的代码,因为 Tomcat 没有提供可以解析 PUT 请求的参数映射。

)下面展示了一段在 NovelsServlet中被重载的 doPost 方法:@Overridepublicvoid doPost(HttpServletRequest request, HttpServletResponse response) {

String author = request.getParameter(“author”); String title = request.getParameter(“title”); …

对于没有报文的 DELETE 请求,过程基本是一样的:@OverridepublicvoiddoDelete(HttpServletRequest request, HttpServletResponse response)

{ String param = request.getParameter(“id”); // id of novel to be removed … doGet 方法需要区分 GET 请求的两种方式:一种是“获得所有”,而另一种是“获得某一个”。

如果 GET 请求 URL 中包含一个键是一个 ID 的查询字符串,那么这个请求就被解析为“获得某一个”:http://localhost:8080/novels?id=2  ## GET specified

如果没有查询字符串,GET 请求就会被解析为“获得所有”:http://localhost:8080/novels       ## GET all一些值得注意的细节“小说”服务的设计反映了像 Tomcat 这样基于 Java 的 web 服务器是如何工作的。

在启动时,Tomcat 构建一个线程池,从中提取请求处理程序,这种方法称为 “ 每个请求一个线程(one thread per request)” 模型现在版本的 Tomcat 使用非阻塞 I/O 来提高个性能。

“小说”服务是作为 NovelsServlet 类的单个实例来执行的,该实例也就维护了一个“小说”集合相应的,也就会出现竞态条件,比如出现两个请求同时被处理:一个请求向集合中添加一个新“小说”另一个请求获得集合中的所有“小说”。

这样的结果是不确定的,取决与 读 和 写 的操作是以怎样的顺序进行操作的为了避免这个问题,“小说”服务使用了线程安全的 ConcurrentMap这个映射的关键是生成了一个线程安全的 AtomicInteger。

下面是相关的代码片段:publicclassNovels {private ConcurrentMap novels; private AtomicInteger mapKey; …

默认情况下,对客户端请求的响应被编码为 XML为了简单,“小说”程序使用了以前的 XMLEncoder 类;另一个包含更丰富功能的方式是使用 JAX-B 库代码很简单:public String toXml

(Object obj) { // default encoding String xml = null; try { ByteArrayOutputStream out = new

ByteArrayOutputStream(); XMLEncoder encoder = new XMLEncoder(out); encoder.writeObject(obj); encoder.close(); xml =

out.toString(); } catch(Exception e) { } return xml; } Object 参数要么是一个有序的“小说” ArraList(用以响应“

获得所有(get all)”请求),要么是一个 Novel 实例(用以响应“ 获得一个(get one)”请求),又或者是一个 String(确认消息)如果 HTTP 请求报头指定 JSON 作为所需要的类型,那么 XML 就被转化成 JSON。

下面是 NovelsServlet 中的 doGet 方法中的检查:String accept = request.getHeader(“accept”); //”accept”is case insensitive

if (accept != null && accept.contains(“json”)) json = true; Novels类中包含了 toJson 方法,可以将 XML 转换成 JSON:public

String toJson(String xml) { // option for requestertry { JSONObject jobt = XML.toJSONObject(xml);

return jobt.toString(3); // 3 is indentation level } catch(Exception e) { } returnnull; } NovelsServlet会对各种类型进行错误检查。

比如,POST 请求应该包含新“小说”的作者和标题如果有一个丢了,doPost 方法会抛出一个异常:if (author == null || title == null) thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST));

SC_BAD_REQUEST 中的 SC 代表的是 状态码(status code),BAD_REQUEST 的标准 HTTP 数值是 400如果请求中的 HTTP 动词是 TRACE,会返回一个不同的状态码:。

publicvoiddoTrace(HttpServletRequest request, HttpServletResponse response){ thrownew RuntimeException(Integer.toString(HttpServletResponse.SC_METHOD_NOT_ALLOWED)); }

测试“小说”服务用浏览器测试 web 服务会很不顺手在 CRUD 动词中,现代浏览器只能生成 POST(创建)和 GET(读取)请求甚至从浏览器发送一个 POST 请求都有点不好办,因为报文需要包含键-值对;这样的测试通常通过 HTML 表单完成。

命令行工具,比如说 curl ,是一个更好的选择,这个部分展示的一些 curl 命令,已经包含在我网站的 ZIP 文件中了下面是一些测试样例,没有展示相应的输出结果:% curl localhost:8080/novels/

% curl localhost:8080/novels?id=1% curl –header “Accept: application/json” localhost:8080/novels/第一条命令请求所有“小说”,默认是 XML 编码。

第二条命令请求 ID 为 1 的“小说”,XML 编码最后一条命令通过 application/json 添加了 Accept 报头元素,作为所需要的 MIME 类型“ 获得一个(get one)”命令也可以用这个报头。

这些请求用了 JSON 而不是 XML 编码作为响应下面两条命令在集合中创建了一个新“小说”,并且确认添加了进去:% curl –request POST –data “author=Tolstoy&title=War and Peace”

localhost:8080/novels/% curl localhost:8080/novels?id=4curl 中的 PUT 命令与 POST 命令相似,不同的地方是 PUT 的报文没有使用标准的语法。

在 NovelsServlet 中关于 doPut 方法的文档中有详细的介绍,但是简单来说,Tomcat 不会对 PUT 请求生成合适的映射下面是一个 PUT 命令和确认命令的的例子:% curl –request PUT –data

“id=3#title=This is an UPDATE” localhost:8080/novels/% curl localhost:8080/novels?id=3第二个命令确认了集合已经更新最后,DELETE 命令会正常运行:

% curl –request DELETE localhost:8080/novels?id=2% curl localhost:8080/novels/这个请求是删除 ID 为 2 的“小说”第二个命令会显示剩余的“小说”。

web.xml 配置文件尽管官方规定它是可选的,web.xml 配置文件是一个生产级别网站或服务的重要组成部分这个配置文件可以配置独立于代码的路由、安全性,或者网站或服务的其他功能“小说”服务的配置通过为该服务的请求分配一个 URL 模式来配置路由:。

novels

>novels.NovelsServletnovels

>/*servlet-name 元素为 servlet 全名(novels.NovelsServlet)提供了一个缩写(novels),然后这个名字在下面的 servlet-mapping 元素中使用。

回想一下,一个已部署服务的 URL 会在端口号后面有 WAR 文件的文件名:http://localhost:8080/novels/端口号后斜杠后的 URI,是所请求资源的“路径”,在这个例子中,就是“小说”服务。

因此,novels 出现在了第一个单斜杠后在 web.xml 文件中,url-patter 被指定为 /*,代表 “以 /novels 为起始的任意路径”假设 Tomcat 遇到了一个不存在的 URL,像这样:。

http://localhost:8080/novels/foobar/web.xml 配置也会指定这个请求被分配到“小说” servlet 中,因为 /* 模式也包含 /foobar因此,这个不存在的 URL 也会得到像上面合法路径的相同结果。

生产级别的配置文件可能会包含安全相关的信息,包括 连接级别(wire-level)和 用户角色(users-roles)即使在这种情况下,配置文件的大小也只会是这个例子中的两到三倍大总结HttpServlet 是 Java web 技术的核心。

像“小说”这样的网站或 web 服务继承了这个类,并且根据需求重载了相应的 do 动词方法像 Jersay(JAX-RS)或 Restlet 这样的 Restful 框架通过提供定制的 servlet 完成了基本相同的功能,针对框架中的 web 应用程序的请求,这个 servlet 扮演着 HTTP(S) 。

终端(endpoint)的角色当然,基于 servlet 的应用程序可以访问 web 应用程序中所需要的任何 Java 库如果应用程序遵循 关注点分离(separation-of-concerns)原则,那么 servlet 代码仍然相当简单:代码会检查请求,如果存在缺陷,就会发出适当的错误;否则,代码会调用所需要的功能(比如,查询数据库,以特定格式为响应编码),然后向请求这发送响应。

HttpServletRequest 和 HttpServletReponse 类型使得读取请求和编写响应变得简单Java 的 API 可以从非常简单变得相当复杂如果你需要用 Java 交付一些 Restful 服务的话,我的建议是在做其他事情之前先尝试一下简单的 HttpServlet。

via: opensource.com作者: Marty Kalin 选题: lujun9972 译者: Yufei-Yan 校对: wxy本文由 LCTT 原创编译, Linux中国 荣誉推出点击“了解更多”可访问文内链接

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容