我正在构建一个基于弹簧的应用程序,用于处理手机游戏应用程序的服务器端游戏管理。该堆栈是Spring/Hibernate/Jersey。我希望客户端(移动设备)调用REST API来更新/检索游戏状态。弹簧非单身控制器
我创建了一个TournamentController
类,它的责任在于使用一些业务逻辑来更新比赛状态。每当需要在锦标赛上进行操作,然后扔掉时,该课程的设计就是如此。
public class TournamentController {
@Autowired
private TournamentDAO tournamentDAO;
private final Tournament tournament;
public TournamentController(Tournament tournament) {
this.tournament = tournament;
}
public void startTournament() {
if (tournament.getState() != TournamentState.SETUP) {
throw new TournamentAlreadyStartedException();
}
tournament.setState(TournamentState.IN_PROGRESS);
//... some other logic and calls to other DAOs
tournamentDAO.save(tournament);
}
}
我还创建了一个TournamentResource
类,它是为比赛的REST前端。它的责任是做一些基本的验证(用户安全,...)和异常翻译。
@Path("/tournament")
@Component
@Scope("prototype")
public class TournamentResource {
private static final Log log = LogFactory.getLog(TournamentResource.class);
@Autowired
private TournamentDAO tournamentDAO;
@GET
@Path("{tournamentId}/start")
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public TournamentDTO startTournament(@PathParam("tournamentId") long tournamentId) {
Tournament tournament = tournamentDAO.getTournament(tournamentId, LockMode.PESSIMISTIC_WRITE);
if (tournament == null) {
throw new WebApplicationException(Status.NOT_FOUND);
}
try {
TournamentController controller = new TournamentController(tournament);
controller.startTournament();
} catch (TournamentAlreadyStartedException e) {
log.warn("Could not start tournament " + tournamentId + " since it is already started.");
throw new RestException(Status.BAD_REQUEST, "Tournament already started");
}
return DTOConverterUtil.getTournament(tournament);
}
}
我使用加载时间与AspectJ编织。这里是我的背景:
<context:annotation-config />
<!-- Make spring aware ANY pojo with the @Configurable annotation -->
<context:spring-configured />
<!-- Scan all classes in com.mdarveau for annotations -->
<context:component-scan base-package="so.question" />
<!-- Load Time Weaver -->
<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" aspectj-weaving="on" />
<!-- DB config -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
...
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.mdarveau.fnp.model" />
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
</value>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- enable @Transactional -->
<tx:annotation-driven transaction-manager="txManager" mode="aspectj" />
我TournamentResource
类是单设计和运作良好。
我的问题是,当它使用new
而不是spring来instanciate TournamentController
时,它的@Autowired
属性似乎没有正确接线。我试图在其上添加@Component
注释,但没有成功。
我应该通过弹簧TournamentResource
ApplicationContextAware
并创建TournamentController
?
这一定是一个相当普遍的问题。我看到很多后端是单例的例子,但是我想避免将Tournament
传递给TournamentController
上的每个方法调用(然后通过TournamentController
中的所有私有方法)。
“TournamentController”基本上只是一个特定“锦标赛”的经理,因此任何时候都必须在比赛中完成某些事情(在任何给定时间将会进行多个锦标赛)。我希望它有一个私人参考“锦标赛”,所以我不必将“锦标赛”的参考传递给每个公共和私人方法。有点像中介模式。 – 2012-04-09 17:45:25
所以它不是无状态的。您需要为用户提供REST方法,以便能够指定他们想要的锦标赛,这将是控制器中的注释方法。它不需要在里面有一个参考。你应该喜欢你不了解REST或调解员。 – duffymo 2012-04-09 17:47:08
是的,这是我的休息方法的“@PathParam(”tournamentId“)”参数:-)。方法get的比赛ID,从持久中检索它,然后实例化TournamentController(传递比赛)引用,以便它可以在请求范围内对其进行操作。 – 2012-04-09 17:49:14