如何在Liferay Dev Studio中基于JAX-RS开发Liferay7.2 REST API后端?
刚好有过在Liferay 7.2里搭建JAX-RS API并对接React的经验,给你梳理一套完整的落地方案,一步步解决你的问题:
Liferay 7.2基于OSGi生态,你的API必须做成OSGi模块(推荐用jar类型,比war更轻量)。下面是我实践下来最清晰的项目结构,分工明确,后续维护也方便:
your-rest-api-module/ ├── src/main/java/ │ ├── com/yourcompany/yourproject/ │ │ ├── rest/ # JAX-RS控制器(处理HTTP请求的入口) │ │ ├── service/ # 核心业务逻辑层 │ │ │ ├── impl/ # 业务逻辑实现类 │ │ │ └── model/ # 数据库表对应的实体类 │ │ ├── persistence/ # 数据访问层(专门和数据库交互) │ │ │ └── impl/ # DAO实现类 │ │ └── config/ # 配置类(比如JAX-RS注册、数据库连接配置) │ └── META-INF/ │ └── resources/ # 静态资源(可选) ├── src/main/resources/ │ └── META-INF/ │ ├── osgi.bnd # OSGi核心配置文件 │ └── persistence.xml # JPA持久化配置 └── pom.xml # Maven依赖管理
各目录的核心作用:
rest/:就是你说的"控制器",负责接收HTTP请求、调用业务层、返回JSON响应service/:封装业务规则,比如数据校验、多表关联逻辑,不直接操作数据库persistence/:只做数据库CRUD,把数据库操作和业务逻辑解耦model/:用JPA注解映射数据库表,对应你说的两张表的实体
Liferay 7.2自带Hibernate作为JPA实现,不用额外装ORM框架,整合起来非常顺:
1. 先在Liferay配置数据源
登录Liferay控制面板,进入配置→系统设置→数据源,添加你的数据库连接(比如MySQL),记住配置的JNDI名称(比如jdbc/yourDB),后面要用到。
2. 添加Maven依赖
在pom.xml里加入必要的依赖,大部分Liferay已经提供,直接用provided scope即可:
<dependencies> <!-- Liferay核心依赖 --> <dependency> <groupId>com.liferay.portal</groupId> <artifactId>com.liferay.portal.kernel</artifactId> <version>7.2.1</version> <scope>provided</scope> </dependency> <!-- JAX-RS规范依赖 --> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.1.1</version> <scope>provided</scope> </dependency> <!-- JPA+Hibernate依赖 --> <dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.12.Final</version> <scope>provided</scope> </dependency> </dependencies>
3. 编写实体类(对应两张表)
假设你有user和order两张表,在service/model/下写实体:
// User.java package com.yourcompany.yourproject.service.model; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "user") public class User { @Id private long userId; private String username; private String email; // 生成getter、setter、无参构造方法 } // Order.java package com.yourcompany.yourproject.service.model; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "order") public class Order { @Id private long orderId; private String orderNumber; // 多对一关联User表 @ManyToOne @JoinColumn(name = "user_id") private User user; // 生成getter、setter、无参构造方法 }
4. 配置JPA持久化单元
在src/main/resources/META-INF/persistence.xml里配置:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2"> <persistence-unit name="yourPU" transaction-type="JTA"> <!-- 这里填你在Liferay里配置的数据源JNDI --> <jta-data-source>jdbc/yourDB</jta-data-source> <class>com.yourcompany.yourproject.service.model.User</class> <class>com.yourcompany.yourproject.service.model.Order</class> <properties> <!-- 根据你的数据库调整方言 --> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <!-- 自动更新表结构(开发环境用,生产环境建议关闭) --> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
5. 编写DAO层(数据访问)
在persistence/下写DAO接口和实现,封装数据库操作:
// UserDAO.java package com.yourcompany.yourproject.persistence; import com.yourcompany.yourproject.service.model.User; import java.util.List; public interface UserDAO { User getById(long userId); List<User> getAll(); void save(User user); } // UserDAOImpl.java package com.yourcompany.yourproject.persistence.impl; import com.yourcompany.yourproject.persistence.UserDAO; import com.yourcompany.yourproject.service.model.User; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.List; public class UserDAOImpl implements UserDAO { // 注入EntityManager,自动关联persistence.xml里的持久化单元 @PersistenceContext(unitName = "yourPU") private EntityManager entityManager; @Override public User getById(long userId) { return entityManager.find(User.class, userId); } @Override public List<User> getAll() { return entityManager.createQuery("SELECT u FROM User u", User.class).getResultList(); } @Override public void save(User user) { entityManager.merge(user); } }
同理编写OrderDAO和OrderDAOImpl即可。
业务逻辑层放在service/下,通过OSGi的服务引用注入DAO,封装业务规则:
// UserService.java package com.yourcompany.yourproject.service; import com.yourcompany.yourproject.service.model.User; import java.util.List; public interface UserService { User getById(long userId); List<User> getAll(); User createUser(User user); } // UserServiceImpl.java package com.yourcompany.yourproject.service.impl; import com.yourcompany.yourproject.persistence.UserDAO; import com.yourcompany.yourproject.service.UserService; import com.yourcompany.yourproject.service.model.User; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import java.util.List; // 注册成OSGi服务,让其他组件可以引用 @Component(service = UserService.class, immediate = true) public class UserServiceImpl implements UserService { // 通过OSGi自动注入DAO实现 @Reference private UserDAO userDAO; @Override public User getById(long userId) { // 这里可以加业务逻辑,比如权限校验、数据脱敏 return userDAO.getById(userId); } @Override public List<User> getAll() { return userDAO.getAll(); } @Override public User createUser(User user) { // 业务逻辑:比如检查用户名是否重复 userDAO.save(user); return user; } }
在rest/下写JAX-RS资源类,作为HTTP请求的入口:
// UserResource.java package com.yourcompany.yourproject.rest; import com.yourcompany.yourproject.service.UserService; import com.yourcompany.yourproject.service.model.User; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants; import java.util.List; // 注册JAX-RS应用,指定基础路径 @Component( property = { JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE + "=/your-api", JaxrsWhiteboardConstants.JAX_RS_NAME + "=YourProject.API", // 允许跨域(对接React需要) "auth.verifier.auth.verifier.PortalSessionAuthVerifier.check.host.name=false" }, service = Object.class ) @Path("/users") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class UserResource { @Reference private UserService userService; @GET public List<User> getAllUsers() { return userService.getAll(); } @GET @Path("/{userId}") public Response getUserById(@PathParam("userId") long userId) { User user = userService.getById(userId); if (user == null) { return Response.status(Response.Status.NOT_FOUND).build(); } return Response.ok(user).build(); } @POST public Response createUser(User user) { User createdUser = userService.createUser(user); return Response.status(Response.Status.CREATED).entity(createdUser).build(); } }
部署后,你的API地址会是http://your-liferay-host:port/o/your-api/users,可以用Postman先测试。
- 用Maven打包:执行
mvn clean install,生成的jar包在target/目录 - 登录Liferay控制面板,进入应用→模块安装,上传jar包即可自动部署
- 部署成功后,在应用→模块管理里能看到你的模块状态为"活跃"
因为React和Liferay大概率跨域,需要做两步:
- 配置跨域:要么在Liferay的
portal-ext.properties里加全局跨域配置:
cors.enabled=true cors.allowed.origins=http://your-react-host:3000 cors.allowed.methods=GET,POST,PUT,DELETE cors.allowed.headers=Content-Type,Authorization
要么在JAX-RS资源类上加上@CrossOrigin注解(JAX-RS 2.1+支持)。
- React调用示例:用
axios或者fetch发起请求:
import axios from 'axios'; // 获取所有用户 const fetchUsers = async () => { try { const response = await axios.get('http://your-liferay-host:8080/o/your-api/users'); console.log(response.data); } catch (error) { console.error('请求失败:', error); } };
如果需要用户认证,可以在请求头里带上Liferay的Cookie(比如JSESSIONID),或者用Liferay支持的OAuth2做身份验证。
内容的提问来源于stack exchange,提问作者Nbenz

