ããã«ã¡ã¯
Spring MVCã¯
ã2014 RevbelLabs Java Tools and Technology Reviewã«ãããšãæã人æ°ã®ããWebãã¬ãŒã ã¯ãŒã¯ã§ãã
ããã«ãåãã¬ãã¥ãŒã§ã¯ORMã®ãªãŒããŒã§ãã
HibernateãšWebã³ã³ãããŒã®ãªãŒããŒã§ããApache TomcatãåŒã³åºããŠããŸãã ããã«ã
jQueryã©ã€ãã©ãªãæã䜿çšãããŠããJavaã¹ã¯ãªãããæã人æ°ã®ãã
Bootstrap cssãã¬ãŒã ã¯ãŒã¯ãæã人æ°ã®ãã
Mavenãã«ãããŒã«ïŒGradleæ»æã«é¢ä¿ãªãïŒã
JUnitãã¹ããã¬ãŒã ã¯ãŒã¯ã®çµ¶å¯ŸçãªãªãŒããŒãè¿œå ããŸãã
Spring Pet Clinic ïŒ
ãã¢ã¢ããªã±ãŒã·ã§ã³ ïŒã
äžèšã«å ããŠãSpring-JdbcãSpring-ORMãæ©èœãããžã§ã¯ãã®èŠ³ç¹ããããã®ããªãã·ã³ãã«ã«å«ãŸããŠããŸãã
Spring Data JPA ã
HibernateããªããŒã¿ãŒ ã
SLF4J ã
ãžã§ã³ãœã³ã»ãžã£ã¯ãœã³JSPJSTL ã
WebJarsã¿ã³ããDataTables ã
HSQLDB ã
ãã ã¯ã¬ã¹ã ã
Mockitoããã³ãã®ä»
å€æ°ã®äŸåé¢ä¿ã
ãœãããŠã§ã¢éçºã®é²æ©ã¯ãçæ³çã«ã¯ã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã®ã¿ã«éã£ãŠãã¢ããªã±ãŒã·ã§ã³èªèº«ã®ã³ãŒãã®éãæžããããšãæå³ããŸãã
ãã ããããã¯ç¡æã§ã¯ãããŸãã-åçŽãªãããžã§ã¯ãã§ãäŸåé¢ä¿ã®æ°ã50ãè¶
ããŠããŸãïŒWEB-INF \ libã®PetClinicã«ã¯61åã®jarããããŸãïŒã
ãã¡ãããããããã¹ãŠãç¥ãå¿
èŠã¯ãããŸãããããã€ãã®ç¶ãããã¯ã°ã©ãŠã³ãã§åŒãäžããããŠãããå®æããæŠäºãèŠããã
mvn project-info-reports:dependencies
å®è¡ã
mvn project-info-reports:dependencies
ïŒIDEAïŒäŸåé¢ä¿ã®è¡šç€º... Mavenãããžã§ã¯ãã§ïŒã ããããããªãã¯äž»ãªãã®ã§äœæ¥ããå¿
èŠããããŸãã ãããŠæŠãããã«
äžéšã®æ©èœã§ã¯ãæ°æéãå Žåã«ãã£ãŠã¯æ°æ¥ãããããšããããŸãã ãããŠããã¬ãŒã ã¯ãŒã¯èªäœã®ãã°ã«å¯ŸåŠããå¿
èŠããããŸã...
æè¿ãPet Clinicã«è§Šçºããããããã®ãã¯ãããžãŒã«é¢ãããŠã§ãããŒãäœæãããšãã«ãTodo管çãªã¹ãã¢ããªã±ãŒã·ã§ã³ãäœæããŸãããto-doãªã¹ã管ç
æ¿èªãšãŠãŒã¶ãŒç»é²ãè¡ããŸãã
Spring Security / Pet Clinicã®äŸåé¢ä¿ã«è¿œå ãããææ°ã®
Spring Security
ãã¹ããš
jQuery
Jeditableããã³
jQueryéç¥ãã©ã°ã€ã³ã
ãã®èšäºã®ããªã¥ãŒã ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äœææé ã説æããããšã¯ã§ããŸããïŒã¢ããªã±ãŒã·ã§ã³ã®äœæã«é¢ãããŠã§ãããŒã¯30æéããããŸãïŒã
ãããã£ãŠãããã§ã¯ããªãœãŒã¹ããã®äœæã®éçšã§çããããã€ãã®èãã決å®ãå
±æããŸãã
PaaS Heroku㧠ãã¢ã¢ããªã±ãŒã·ã§ã³ãèŠã€ããããšãã§ããŸãïŒæåã«
èµ·åæã«é·ãããŠã³ããŒããšãµãŒããŒãšã©ãŒãçºçããå¯èœæ§ãããå Žåã¯ãç¹°ãè¿ããŸãïŒã
å¿çšäŸ
ã€ã³ã¿ãŒãããã«ã¯ãSpring / JPA / MVC / Securityã§æ§ç¯ãããå€ãã®ã¢ããªã±ãŒã·ã§ã³ããããŸãã ãœãŒããããŠã³ããŒãããæé©ãªãœãªã¥ãŒã·ã§ã³ãéžæã§ããŸãã
Springåå空éã®æ§æ
Springæ§æã§ã¯ãåå空éã®äžã«å®è£
ã®è©³çŽ°ãé ãåŸåããããŸãã
æ§æã¯å°ãããªããç解ãããããªããŸãããã«ã¹ã¿ãã€ãºãŸãã¯ãããã°ã®ããã»ã¹ã¯ããã»ã©ç°¡åã§ã¯ãããŸããããŸãããã³ãèŠã€ããå¿
èŠããããŸãã
ã©ãã«å®è£
ãããŠããŸããã
åæåã®äŸã®æ¯èŒ
ããŒã¹ ïŒ
<bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer" depends-on="entityManagerFactory"> <property name="databasePopulator" ref="resourceDatabasePopulator"/> <property name="dataSource" ref="dataSource"/> </bean> <bean id="resourceDatabasePopulator" class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator"> <property name="scripts"> <array> <value>classpath*:db/${jdbc.initLocation}</value> <value>classpath*:db/populateDB.sql</value> </array> </property> </bean>
ãããŠ
<jdbc:initialize-database data-source="dataSource" enabled="${database.init}"> <jdbc:script location="classpath:db/${jdbc.initLocation}"/> <jdbc:script location="classpath:db/populateDB.sql"/> </jdbc:initialize-database>
ããã¯ã以åã®Acegi SecurityãšSpring Securityãæ¯èŒãããšãã«ç¹ã«é¡èã§ãïŒãã¹ãŠã®ãã£ã«ã¿ãŒã¯
åå空ésecurityã®äžã«é ãããŠã
ãŸã ïŒã
ãã¹ãã®@Transactional
Springã®ãã¹ãã§ã¯ããã©ã³ã¶ã¯ã·ã§ã³æ§ã䜿çšããã®ãäžè¬çã§ããåãã¹ãã®å®è¡åŸãããŒã¹ããŒã«ããã¯ã¯å
ã®ç¶æ
ã«æ»ããŸãã
ãã ãã@ Transactionalèªäœããã¹ãã®åäœã«åŒ·ã圱é¿ããŸããããšãã°ã@ TransactionalãµãŒãã¹/ãªããžããªãå¿ããŠããŸãããã¹ãã«åæ Œããã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ããŸããã
ããã«æªãããšã«ããã¹ããããŒã¿ããŒã¹ãããšã³ãã£ãã£ãååŸããŠæ¯èŒããå ŽåïŒ
ãããã¯åããã©ã³ã¶ã¯ã·ã§ã³ã³ã³ããã¹ãã«åé¡ããããã¹ããããã¡ãœããã®åäœã¯å€å°ç°ãªããŸãïŒã»ãŒãã®åé€ãŸãã¯ãã¿ããã®ã¿ïŒã
ãã¹ããããã°äžã®åºæ¬ç¶æ
ãããã¹ããã©ã³ã¶ã¯ã·ã§ã³ãå®äºãããŸã§è¡šç€ºãããŸããã
åãã¹ãã®åã«ããŒã¹åæååã䜿çšããæ¹ãããæ£çŽã§ãã
<bean class="DbPopulator"> <constructor-arg name="scriptLocation" value="classpath:db/populateDB.sql"/> </bean>
public class DbPopulator extends ResourceDatabasePopulator { private static final ResourceLoader RESOURCE_LOADER = new DefaultResourceLoader(); @Autowired private DataSource dataSource; public DbPopulator(String scriptLocation) { super(RESOURCE_LOADER.getResource(scriptLocation)); } public void execute() { DatabasePopulatorUtils.execute(this, dataSource); } } @ContextConfiguration("classpath:spring/spring-app.xml") @RunWith(SpringJUnit4ClassRunner.class) @ActiveProfiles({"postgres", "jpa"}) public class TodoItemServiceTest { @Autowired private DbPopulator dbPopulator; @Before public void setUp() throws Exception { dbPopulator.execute(); }
æŽæ°ïŒSpring 4.1ã§ã¯ãDbPopulatorã«ä»£ãã泚éãå°å
¥ãããŸããã
@org.springframework.test.context.jdbc.Sql
EntityManagerFactoryã®èšå®
persistence.xmlã§å®£èšãããŠããªããšã³ãã£ãã£ã«é¢ããSpring 3.0ã®ãã°ã«æ
£ããŠããã®ã§ãããããªããŠããã¹ãŠãæ©èœããããšã«é©ããŸããïŒ
ã³ãŒããå°ãæãäžããåŸããã¹ãŠã®ã¿ãŒã²ãã/ã¯ã©ã¹ããšã³ãã£ãã£ã¢ãããŒã·ã§ã³ã«ã€ããŠã¹ãã£ã³ãããããšãããããŸããã ãŸããpersistence.xmlã䜿çšããã«JPAãæ§æã§ããããšã«ãæºè¶³ããŠããŸãã
ã¢ãã«ãã¹ãã£ã³ããããã®ç¹å®ã®ããã±ãŒãžãæå®ãããããã€ããŒåºæã®äžè¬çãªJPAãã©ã¡ãŒã¿ãŒãæ§æã§ããŸãã
ãããŠãããããå
±éã®db.propertiesãã¡ã€ã«ã«ç§»åã§ããŸãïŒ
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="**.model"> <property name="jpaPropertyMap"> <map> <entry> <key> <util:constant static-field="org.hibernate.cfg.AvailableSettings.FORMAT_SQL"/> </key> <value>${hibernate.format_sql}</value> </entry> <entry> <key> <util:constant static-field="org.hibernate.cfg.AvailableSettings.USE_SQL_COMMENTS"/> </key> <value>${hibernate.use_sql_comments}</value> </entry> </map> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:showSql="${jpa.showSql}" p:generateDdl="${jpa.generateDdl}"> </bean> </property> </bean>
æ¥ç¶ããŒã«ã®å®è£
ã®éžæã
DataSource
Commons DBCPãå®è£
ãããšããåŸæ¥ã®éžæã¯ã
å°æ©ã倱ã£ãŠããããã§ãã
StackOverflowã«ãããšãå®è£
ã«ã¯
ãã¬ã€ãã¬ãŒã ã¯ãŒã¯ã§äœ¿çšããã
BoneCPã䜿çšããå¿
èŠããããŸãïŒæ¢ã«äœ¿çšããŠããå ŽåããŸãã¯äœ¿çšããå Žåã¯ã
éçºè
Plumbrããã®ã¬ããŒãã§è¡šæãããã¡ã¢ãªãªãŒã¯ãåé¿ããããã«ãããã€ãã®åªåãå¿
èŠã§ããããšã«æ³šæããŠãã ããã
ãŸããPetClinic
ã¯tomcat-jdbcã䜿çšããŸã ã
ã¢ããªã±ãŒã·ã§ã³ãTomcatã«ãããã€ãããŠããå Žåãwarã«å«ããããšã¯ã§ããŸããïŒscope =æäŸïŒããåæã«$ TOMCAT_HOME / libã«å«ããããšãã§ããŸã
ãã€ãã£ãã®tomcat-jdbcããæŠäºã®ã©ã€ãã©ãªãå©çšã§ããªããããããŒã¹ãã©ã€ããŒãé
眮ããå¿
èŠããããŸãã
ãããŠãã¡ãããTomcatã«ãããã€ãããšãã¯ãæ¥ç¶ããŒã«ãååŸããæ©èœãå¿ããªãã§ãã ãã
Tomcatæ§æcontext.xmlãªãœãŒã¹ïŒ
<beans profile="jndi"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/javatop"/> </beans>
EntityManagerã«åºã¥ãã¡ã€ã³CRUDã®å®è£
ã§ãšã³ãã£ãã£ãšããŒã«ãã£ãŠãã©ã¡ãŒã¿ãŒåãããç¬èªã®AbstractDAOãäœæããããã«åãããžã§ã¯ãã«æ
£ããŠããããšã¯åã°ããããšã§ãããã
ãããã圌ã¯ã€ãã«Spring Data JPAãããžã§ã¯ãã§Springã«åå
¥ããŸããïŒ
JpaRepository<T, ID extends Serializable>
ããäžè¬çãª
CrudRepository<T, ID extends Serializable>
ç¶æ¿ã
CrudRepository<T, ID extends Serializable>
Spring Data Commonsããã
JPAãªããžããªãæäœããããšã¯ ãæå
ã¯é©ãã¹ãããšã§ãã
public interface UserRepository extends Repository<User, Integer> { User findByEmail(String email); }
ãããŠãã¡ãœããèªäœã¯åäžã®å®è£
è¡ãªãã§æ©èœããŸãïŒ
äž»ãªæ
å ±æºãžã®ã¢ããŒã«ã¯ãéæ³ã®å
éšããããã·ãæ£èŠè¡šçŸããªãã¬ã¯ã·ã§ã³ã§ããããšã瀺ããŸããã
èªè
ãžã®ä¿®èŸçãªè³ªåïŒjavaã¯åçèšèªãšèŠãªãããšãã§ããŸã:)ïŒ
JpaRepositoryãšçæãããã¡ãœãããååã§ãªãå Žå
ãç¬èªã®ã¡ãœãããŸãã¯Queryã¯ãšãªã®å®è£
ãèšè¿°ã§ã
ãŸã ã
@Query
JPQLã¯ãšãªïŒ@NamedQueryã§çæãããïŒã
@NamedQuery
ã§ããŸãããŸãã¯ããšã³ãã£ãã£ã§æ¢ã«å®£èšãããŠãã
@NamedQuery
åç
§ã§ããŸãïŒäœããã®çç±ã§ãPetClinic
@NamedQuery
ãã®ãããªèŠæ±ã¯æ§ç¯æ®µéã§æ§ç¯ããã³ãã§ãã¯ãããŸãããç¡èŠãããŸãïŒã
ããšãã°ãã¡ãœãã
@Modifying @Transactional @Query(name = User.DELETE) int delete(@Param("id") int id);
ãŠãŒã¶ãŒ@NamedQueryã§å®£èšãããåç
§
@NamedQueries({ ... @NamedQuery(name = User.DELETE, query = "DELETE FROM User u WHERE u.id=:id") }) public class User extends NamedEntity { public static final String DELETE = "User.delete";
void CrudRepository.delete(ID id)
ãšã¯ç°ãªããå€æŽãããã¬ã³ãŒãã®æ°ãè¿ããŸãã
ãã ããåé¡ããããŸã
JpaRepository
ããããžãã¹ããŒã¿ã¢ã¯ã»ã¹ã€ã³ã¿ãŒãã§ã€ã¹ã
JpaRepository
ãããšããµãŒãã¹ã¬ãã«ãå®è£
ã«äŸåããããšã«ãªããŸãã
ãŸããããšãã°ã
List<T> findAll(Sort sort)
ã¡ãœããã§ã¯ã
List<T> findAll(Sort sort)
ã¯ã©ã¹ãSpring Dataã«ããããããµãŒãã¹ã§èšå®ããå¿
èŠã¯ãããŸããã
ã€ã³ã¿ãŒãã§ã€ã¹ã¡ãœããã®çœ²åã¯ã
JpaService
眲åã«ãã€ã³ããããŸãã ãããŒã¹ããŠãã°ã€ã³ããã®ã¯äžäŸ¿ã§ãã ãµãŒãã¹ã¬ãã«ã§ãŸã£ããå¿
èŠã®ãªããã¹ãŠã®
JpaRepository
ã¡ãœããããŸãã¯
org.springframework.data.repository.Repository
ããŒã¯ã³ããç¶æ¿ããå Žåã
JpaRepository
æ€èšŒã¯è¡ããã
@Override
...
ãããã®åé¡ã¯ãã¹ãŠãå¥ã®ã¬ãã«ã®å§ä»»ã«ãã£ãŠè§£æ±ºãããŸãã
public interface ProxyUserRepository extends JpaRepository<User, Integer> { @Modifying @Query("DELETE FROM User u WHERE u.id=?1") @Transactional int delete(int id); @Override @Transactional User save(User user); @Override User findOne(Integer id); @Override List<User> findAll(Sort sort); } @Repository public class DataJpaUserRepository implements UserRepository { private static final Sort SORT_NAME_EMAIL = new Sort("name", "email"); @Autowired private ProxyUserRepository proxy; @Override public boolean delete(int id) { return proxy.delete(id) != 0; } @Override public User save(User user) { return proxy.save(user); } @Override public User get(int id) { return proxy.findOne(id); } @Override public List<User> getAll() { return proxy.findAll(SORT_NAME_EMAIL); } }
æåŸã«ïŒãããã¯ãªãœãŒã¹
æ¥
ã¡ã€ãŽã³
ãã®ã³ã°
æç¶æ§
ãã®èšäºãæ°ã«å
¥ã£ãããäžé©åãªSpring MVCãSpring SecurityãJacksonãªã©ã§ããŒã2ãæºåããŸãã
ãæž
èŽããããšãããããŸãããåãäžãããããããã¯ã«ã€ããŠãæèŠããèãããã ããã