Jersey服務類為介面時出現java.lang.NoSuchMethodException
在使用Jersey時,把提供服務的類設計為介面,配置在web.xml中,運行Tomcat之後訪問服務出現異常:
java.lang.NoSuchMethodException: Could not find a suitable constructor in coursemanager.resource.CourseResource class.
情景
使用的bean:
package coursemanager.bean;/** * 課程 */public class Course { /** * 課程ID */ private Integer id; /** * 課程名稱 */ private String name; /** * 教授老師 */ private String teacher; /** * 教室地點 */ private String location; /** * 學生人數 */ private Integer studentNum; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTeacher() { return teacher; } public void setTeacher(String teacher) { this.teacher = teacher; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public Integer getStudentNum() { return studentNum; } public void setStudentNum(Integer studentNum) { this.studentNum = studentNum; } public Course() { } public Course(String name, String teacher, String location, Integer studentNum) { super(); this.name = name; this.teacher = teacher; this.location = location; this.studentNum = studentNum; } public Course(Integer id, String name, String teacher, String location, Integer studentNum) { super(); this.id = id; this.name = name; this.teacher = teacher; this.location = location; this.studentNum = studentNum; } @Override public String toString() { return "Course [id=" + id + ", name=" + name + ", teacher=" + teacher + ", location=" + location + ", studentNum=" + studentNum + "]"; }}
聲明服務的介面:
package coursemanager.resource;import javax.ws.rs.Consumes;import javax.ws.rs.DELETE;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.PUT;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.QueryParam;import javax.ws.rs.core.MediaType;import coursemanager.bean.Course;/** * 課程資源 */@Path("course")public interface CourseResource { /** * 儲存課程資訊 * 接收json資訊 * 返回課程的資源地址 * @param course 課程 * @return 成功新課程的id,失敗返回"error" */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.TEXT_PLAIN) public Integer save(Course course); /** * 刪除課程 * @param id 課程ID * @return 成功返回"success",失敗返回"error" */ @DELETE @Path("{id:\\d+}") public String delete(@PathParam("id") Integer id); /** * 更新課程資訊 * @param course 課程 * @return 成功返回"success",失敗返回"error" */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.TEXT_PLAIN) public String update(Course course); /** * 擷取特定ID的課程資訊 * @param id 課程ID * @return 課程 */ @GET @Path("{id:\\d+}") @Produces(MediaType.APPLICATION_JSON) public Course get(@PathParam("id") Integer id); /** * 通過課程名字查詢課程資訊 * @param name * @return */ @GET @Produces(MediaType.APPLICATION_JSON) public Course getByCourseName(@QueryParam("name") String name);}
介面的實作類別:
package coursemanager.impl;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import coursemanager.bean.Course;import coursemanager.resource.CourseResource;public class CourseResourceImpl implements CourseResource { public static Integer courseId = 0; public static List<Course> courses = new ArrayList<Course>(); public CourseResourceImpl() { System.out.println("初始化5條記錄"); // 添加5個記錄 for (int i = 1; i <= 5; i++) { Course course = new Course("課程" + i, "教師" + i, "地點" + i, 50); addCourse(course); } } @Override public Integer save(Course course) { addCourse(course); return course.getId(); } @Override public String delete(Integer id) { Iterator<Course> iter = courses.iterator(); while (iter.hasNext()) { Course course = iter.next(); if (course.getId().equals(id)) { courses.remove(course); courseId--; return "success"; } } return "error"; } @Override public String update(Course course) { Iterator<Course> iter = courses.iterator(); while (iter.hasNext()) { Course co = iter.next(); if (co.getId().equals(course.getId())) { courses.remove(co); courses.add(course); return "success"; } } return "error"; } @Override public Course get(Integer id) { Iterator<Course> iter = courses.iterator(); while (iter.hasNext()) { Course course = iter.next(); if (course.getId().equals(id)) { return course; } } return null; } @Override public Course getByCourseName(String name) { Iterator<Course> iter = courses.iterator(); while (iter.hasNext()) { Course course = iter.next(); if (course.getName().equals(name)) { return course; } } return null; } private void addCourse(Course course) { courseId++; course.setId(courseId); courses.add(course); }}
在web.xml中的配置:
<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>coursemanager</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
訪問http://localhost:8080/coursemanager/course/1,觸發異常
嚴重: Servlet.service() for servlet [Jersey Web Application] in context with path [/coursemanager] threw exception [A MultiException has 1 exceptions. They are:1. java.lang.NoSuchMethodException: Could not find a suitable constructor in coursemanager.resource.CourseResource class.] with root causejava.lang.NoSuchMethodException: Could not find a suitable constructor in coursemanager.resource.CourseResource class. at org.glassfish.jersey.internal.inject.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:192) at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:178) at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:988) at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:962) at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1054) at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1046) at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173) at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:284) at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74) at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:109) at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:92) at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:61) at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197) at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:318) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:267) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) at coursemanager.filter.EncodingFilter.doFilter(EncodingFilter.java:36) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org