Liferay 7 + Spring MVC + JAX-RS:Spring MVC Portlet配置JAX-RS服务求助
Hey there! Since you're already working on adding JAX-RS web services to your Spring MVC Portlet project in Liferay and have done some initial groundwork, let's break down the critical steps to get this running smoothly, plus troubleshoot common pitfalls you might hit.
First, make sure your pom.xml has the right dependencies to bridge Spring MVC Portlet, JAX-RS, and Liferay's extender. You'll need:
<!-- Liferay's JAX-RS Extender (provided by Liferay, so scope is provided) --> <dependency> <groupId>com.liferay</groupId> <artifactId>com.liferay.jaxrs.extender</artifactId> <version>${liferay.version}</version> <scope>provided</scope> </dependency> <!-- Spring + JAX-RS integration --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-spring</artifactId> <version>${resteasy.version}</version> <exclusions> <!-- Exclude conflicting Spring versions if needed --> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> </exclusions> </dependency>
Pro tip: Use the same Spring version as your Liferay instance to avoid dependency conflicts.
Your JAX-RS resource needs to be managed by Spring and have the standard JAX-RS annotations. Here's a working example:
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.springframework.stereotype.Component; // Mark as a Spring component so it's scanned and managed @Component @Path("/my-portlet-services") // Base path for this resource public class PortletRestResource { @GET @Path("/greet") @Produces(MediaType.APPLICATION_JSON) public String getGreeting() { return "{\"message\": \"Hello from JAX-RS in Spring MVC Portlet!\"}"; } }
Don't forget to enable component scanning in your spring-portlet.xml so Spring finds this class:
<context:component-scan base-package="com.your.project.package.resources" />
You mentioned configuring the extender in the control panel—let's make that setup align with your code:
- If you're using a Spring-managed
Applicationclass (recommended), create one like this to avoid manual control panel config:
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import org.springframework.stereotype.Component; @Component @ApplicationPath("/my-rest-api") // Root path for all your JAX-RS services public class RestApplication extends Application { // Empty is fine—Resteasy will auto-scan Spring-managed JAX-RS resources }
- If you prefer manual control panel setup:
- Go to Control Panel → Configuration → System Settings → Foundation → JAX-RS Application
- Add a new application with:
- Name: A descriptive name (e.g., "Spring Portlet REST App")
- Context Path:
/my-rest-api(matches your@ApplicationPathif using that) - Application Class: Leave blank if using Spring scanning, or specify your
RestApplicationclass
Once deployed, test your service at:http://your-liferay-domain:port/o/my-rest-api/my-portlet-services/greet
(Note: Liferay adds the /o/ prefix to all REST endpoints by default.)
If it's not working, check these common issues:
- Log Checks: Look for errors in Liferay's logs (e.g., resource not found, dependency conflicts, Spring scanning failures)
- Annotation Typos: Double-check
@Path,@Produces, and@Componentannotations—small typos break everything - Dependency Conflicts: Use
mvn dependency:treeto spot conflicting Spring/Resteasy versions - Scanning Scope: Ensure your
component-scanin Spring covers the package where your JAX-RS resource lives
JAX-RS services run in Liferay's servlet context, not the portlet context. That means their URLs don't tie to your portlet's render/action URLs—they're standalone endpoints accessible directly via the HTTP path we tested earlier.
内容的提问来源于stack exchange,提问作者MrC0mm0n

