“Resteasy with maven”的版本间的差异

来自软件实验室
跳转至: 导航搜索
部署
进一步的问题
第223行: 第223行:
 
</dependency>
 
</dependency>
 
</nowiki>
 
</nowiki>
 +
== 同时响应多种请求格式 ==
 +
不同的客户端可能青睐不同的数据格式,比如Javascript喜欢json,Java喜欢xml,ruby喜欢YAML,你可以针对每种数据格式写一个响应方法,比如:
 +
 +
<nowiki>
 +
</nowiki>
 +
 +
但是,这样写代码好麻烦啊!幸运的是,JAX-RS API已经帮我们想到了这一点,下面是JAX-RS处理不同数据格式请求的过程:
 +
[[文件:jaxrs-request-dispatch.png]]
 +
 +
因此,只要定义一个这样的方法即可应对XML,JSON两种格式的数据请求:
 +
<nowiki>
 +
</nowiki>
 +
 +
当然,模型类Student也要做相应的修改:
 +
<nowiki>
 +
</nowiki>
 +
 +
 +
===模型类最佳实践 ===
 +
  <nowiki>
 +
</nowiki>
 +
 +
 +
 
== 进一步的问题 ==
 
== 进一步的问题 ==
 
* 为什么wildfly:deploy把war文件部署到了standalone/data/content目录下,而不是standalone/deployments目录下?eclipse下面运行wildfly是部署到deployments目录下的。
 
* 为什么wildfly:deploy把war文件部署到了standalone/data/content目录下,而不是standalone/deployments目录下?eclipse下面运行wildfly是部署到deployments目录下的。
 
* eclpse的maven支持难道真的有点问题?为什么不能自动刷新加入的依赖关系,通常需要close project & reopen project才会生效。
 
* eclpse的maven支持难道真的有点问题?为什么不能自动刷新加入的依赖关系,通常需要close project & reopen project才会生效。

2015年12月15日 (二) 13:05的版本

环境说明

  • maven 3.3.9
  • wildfly 9.0.2
  • resteasy:wildfly自带,版本3.0.11.Final

使用maven创建项目

使用下列命令创建示例项目:

mvn archetype:generate  -DgroupId=cn.edu.sdut.r314  -DartifactId=helloRest  -DarchetypeArtifactId=maven-archetype-webapp  -DinteractiveMode=false

也可以交互方式创建项目,步骤如下:

  1. 执行命令 mvn archetype:generate
  2. 在接下来的众多archetype中,输入webapp筛选缩小范围,目前列出了86个符合webapp的archetype,我们这里使用第22个archetype,创建一个简单的webapp的框架:
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 703: webapp
Choose archetype:
1: remote -> br.com.ingenieux:elasticbeanstalk-docker-dropwizard-webapp-archetype (A Maven Archetype for Publishing Dropwizard-based Services on AWS' Elastic Beanstalk Service)
......
21: remote -> org.apache.marmotta:marmotta-archetype-webapp (Web Application bundle (WAR file) containing Apache Marmotta)
22: remote -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
......
86: remote -> uk.ac.rdg.resc:edal-ncwms-based-webapp (-)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 22


  1. 在接下来的交互中,输入合适的groupId(包名),artifactId(项目名)即可成功创建项目框架。

项目导入到eclipse

为了方便项目文件的编辑,可以将maven创建的项目导入到eclipse中进行管理。

由于我们用不到jsp文件,将src/main/webapp目录下的index.jsp删除即可。

修改pom.xml

初始的pom.xml文件是这个样子的:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>cn.edu.sdut.r314</groupId>
	<artifactId>helloRest</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>helloRest Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>helloRest</finalName>
	</build>
</project>

可以看出,maven-archetype-webapp这个archetype创建的项目默认已经添加了junit的依赖。虽然我们这个示例程序暂时没有涉及单元测试的内容,我们还是保留junit的依赖设置,方便以后增加单元测试的内容。本实例当然需要增加resteasy的依赖设置,另外由于我们要把应用部署到wildfly,因此增加了部署wildfly应用的plugin,修改后的pom.xml文件如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>cn.edu.sdut.r314</groupId>
	<artifactId>helloRest</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>helloRest Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<version>3.0.11.Final</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>helloRest</finalName>
		<plugins>
			<plugin>
				<groupId>org.wildfly.plugins</groupId>
				<artifactId>wildfly-maven-plugin</artifactId>
				<version>1.1.0.Alpha4</version>
			</plugin>
		</plugins>

	</build>
</project>

由于wildfly 9.0.2内置了resteasy 3.0.11.Final,因此我们的示例程序对resteasy的依赖声明为provided scope,即告诉wildfly,我们使用wildfly自带的resteasy实现(参见wildfly的modules/system/layers/base/org/jboss/resteasy目录)。如果去掉scope声明,则使用我们指定的resteasy实现。换言之,如果resteasy的scope为provided,则打包后的应用不包含resteasy-jaxrs.jar;如果resteasy的scope省略,则打包后的应用会包含resteasy-jaxrs.jar。

在完成这个示例后,可以分别观察删除和保留resteasy-jaxrs的<scope>provided</scope>时,target/helloRest/WEB-INF目录的不同布局:当删除scope声明时,WEB-INF会生成一个lib目录,将resteasy-jaxrs及其依赖包包含进来;而scope声明为provided时,target/helloRest/WEB-INF下面不会生成lib目录。

创建一个空的web.xml

由于wildfly已经集成了resteasy,已经不需要在web.xml声明servlet映射等了,只需要放一个空的web.xml在webapp/WEB-INF目录即可:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">
</web-app>

编写服务器端的service

由于maven-archetype-webapp没有正确的创建java目录和包,需要我们手工创建:在src/main目录下创建java/cn/edu/sdut/r314目录(可以通过在eclipse创建相应的包名的方式创建此目录),我们服务器端的service即安放在这个目录下。同时,在src/创建test/java,将来的单元测试放在这里。

继续编写服务器端的service代码之前,请确保eclipse已经根据maven更新了项目的依赖包。由于eclipse的某个bug(或者设置问题?),有的时候eclipse并不能及时的根据修改后的pom.xml及时的更新项目的依赖库,导致代码自动提示功能失效。如果遇到此种情况,可以尝试close project然后reopen。目前正确的项目依赖关系如下图所示:

Maven-resteasy-dep.png

编写BaseApplication.java

代码如下:

package cn.edu.sdut.r314;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("")
public class BaseApplication extends Application {

}


编写模型类Student.java

package cn.edu.sdut.r314;

public class Student {
	private String name;
	private int javaGrade; // java课程成绩
	
	public Student(String name, int javaGrade) {
		super();
		this.name = name;
		this.javaGrade = javaGrade;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getJavaGrade() {
		return javaGrade;
	}
	public void setJavaGrade(int javaGrade) {
		this.javaGrade = javaGrade;
	}
}


编写HelloService.java

代码如下:

package cn.edu.sdut.r314;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("")
public class HelloService {

	@GET
	@Path("hello")
	@Produces(MediaType.APPLICATION_JSON)
	public Student sayHello(){
		return new Student("zhangsan",95);
	}
}

部署

ok,首先将wildfly启动起来,然后在项目的根目录下执行如下指令部署应用:

mvn clean package wildfly:deploy

如果一切顺利,会显示:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.645 s
[INFO] Finished at: 2015-12-14T20:29:08+08:00
[INFO] Final Memory: 25M/197M
[INFO] ------------------------------------------------------------------------


打开一个浏览器窗口测试一下吧!

Resteasy maven json output.png

json格式问题

但是,且慢!在返回的json对象中,可以看到javaGrade不太符合json的一般写法java_grade。这就需要在Student类上面增加jackson的注解把javaGrade映射为java_grade:

	@JsonProperty("java_grade")  
	private int javaGrade; // java课程成绩

但是默认情况下JsonProperty所属的包com.fasterxml.jackson.annotation并没有导入到项目的编译路径,因此需要在pom.xml文件增加如下的依赖设置:

		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jackson2-provider</artifactId>
			<version>3.0.11.Final</version>
			<scope>provided</scope>
		</dependency>

同时响应多种请求格式

不同的客户端可能青睐不同的数据格式,比如Javascript喜欢json,Java喜欢xml,ruby喜欢YAML,你可以针对每种数据格式写一个响应方法,比如:


但是,这样写代码好麻烦啊!幸运的是,JAX-RS API已经帮我们想到了这一点,下面是JAX-RS处理不同数据格式请求的过程: 文件:Jaxrs-request-dispatch.png

因此,只要定义一个这样的方法即可应对XML,JSON两种格式的数据请求:


当然,模型类Student也要做相应的修改:



模型类最佳实践

 


进一步的问题

  • 为什么wildfly:deploy把war文件部署到了standalone/data/content目录下,而不是standalone/deployments目录下?eclipse下面运行wildfly是部署到deployments目录下的。
  • eclpse的maven支持难道真的有点问题?为什么不能自动刷新加入的依赖关系,通常需要close project & reopen project才会生效。