Redditアプリケーションの改善の最初のラウンド
1. 概要
The Reddit web application Case Studyは順調に進んでおり、小さなWebアプリケーションは形を整え、ゆっくりと使用できるようになっています。
今回の記事では、既存の機能に小さな改善を加えます。外部に面しているものとそうでないものがあり、通常はmaking the app betterです。
2. セットアップチェック
アプリケーションがブートストラップされたときに実行する必要がある、いくつかの単純ですが便利なチェックから始めましょう。
@Autowired
private UserRepository repo;
@PostConstruct
public void startupCheck() {
if (StringUtils.isBlank(accessTokenUri) ||
StringUtils.isBlank(userAuthorizationUri) ||
StringUtils.isBlank(clientID) || StringUtils.isBlank(clientSecret)) {
throw new RuntimeException("Incomplete reddit properties");
}
repo.findAll();
}
ここで@PostConstructアノテーションを使用して、依存性注入プロセスが終了した後、アプリケーションのライフサイクルにフックする方法に注意してください。
単純な目標は次のとおりです。
-
Reddit APIにアクセスするために必要なすべてのプロパティがあるかどうかを確認します
-
永続層が機能していることを確認します(単純なfindAll呼び出しを発行することにより)
失敗した場合-早く失敗します。
3. 「リクエストが多すぎる」Redditの問題
Reddit APIは、一意の「User-Agent」を送信しないレート制限リクエストに積極的です。
したがって、カスタムInterceptorを使用して、この一意のUser-AgentヘッダーをredditRestTemplateに追加する必要があります。
3.1. カスタムInterceptorを作成する
これがカスタムインターセプターです–UserAgentInterceptor:
public class UserAgentInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(
HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
headers.add("User-Agent", "Schedule with Reddit");
return execution.execute(request, body);
}
}
3.2. redditRestTemplateを構成する
もちろん、使用しているredditRestTemplateでこのインターセプターを設定する必要があります。
@Bean
public OAuth2RestTemplate redditRestTemplate(OAuth2ClientContext clientContext) {
OAuth2RestTemplate template = new OAuth2RestTemplate(reddit(), clientContext);
List list = new ArrayList();
list.add(new UserAgentInterceptor());
template.setInterceptors(list);
return template;
}
4. テスト用にH2データベースを構成する
次へ–先に進んで、テスト用にインメモリDB – H2 –をセットアップしましょう。 この依存関係をpom.xmlに追加する必要があります。
com.h2database
h2
1.4.187
そして、persistence-test.propertiesを定義します。
## DataSource Configuration ###
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:oauth_reddit;DB_CLOSE_DELAY=-1
jdbc.user=sa
jdbc.pass=
## Hibernate Configuration ##
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=update
5. Thymeleafに切り替えます
JSPはアウトで、Thymeleafはインです。
5.1. pom.xmlを変更する
まず、pom.xmlにこれらの依存関係を追加する必要があります。
org.thymeleaf
thymeleaf
2.1.4.RELEASE
org.thymeleaf
thymeleaf-spring4
2.1.4.RELEASE
org.thymeleaf.extras
thymeleaf-extras-springsecurity3
2.1.2.RELEASE
5.2. ThymeleafConfigを作成します
次へ–単純なThymeleafConfig:
@Configuration
public class ThymeleafConfig {
@Bean
public TemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/jsp/");
templateResolver.setSuffix(".jsp");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new SpringSecurityDialect());
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
return viewResolver;
}
}
そしてそれをServletInitializerに追加します:
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(PersistenceJPAConfig.class, WebConfig.class,
SecurityConfig.class, ThymeleafConfig.class);
return context;
}
5.3. home.htmlを変更する
ホームページの簡単な変更:
Schedule to Reddit
6. ログアウト
それでは、アプリケーションのエンドユーザーに実際に表示されるいくつかの改善を行いましょう。 ログアウトから始めます。
セキュリティ設定を変更して、アプリケーションに簡単なログアウトオプションを追加します。
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.....
.and()
.logout()
.deleteCookies("JSESSIONID")
.logoutUrl("/logout")
.logoutSuccessUrl("/");
}
7. Subredditオートコンプリート
次へ– subredditを埋めるためにa simple autocomplete functionalityを実装しましょう。手動で書くのは良い方法ではありません。間違える可能性がかなりあるからです。
クライアント側から始めましょう:
とても簡単です。 さて、サーバー側:
@RequestMapping(value = "/subredditAutoComplete")
@ResponseBody
public String subredditAutoComplete(@RequestParam("term") String term) {
MultiValueMap param = new LinkedMultiValueMap();
param.add("query", term);
JsonNode node = redditRestTemplate.postForObject(
"https://oauth.reddit.com//api/search_reddit_names", param, JsonNode.class);
return node.get("names").toString();
}
8. リンクがすでにRedditにあるかどうかを確認する
次へ–リンクが以前にRedditに送信されているかどうかを確認する方法を見てみましょう。
submissionForm.htmlは次のとおりです。
そして、ここにコントローラーメソッドがあります:
@RequestMapping(value = "/checkIfAlreadySubmitted", method = RequestMethod.POST)
@ResponseBody
public String checkIfAlreadySubmitted(
@RequestParam("url") String url, @RequestParam("sr") String sr) {
JsonNode node = redditRestTemplate.getForObject(
"https://oauth.reddit.com/r/" + sr + "/search?q=url:" + url + "&restrict_sr=on", JsonNode.class);
return node.get("data").get("children").toString();
}
9. Herokuへのデプロイ
最後に、Herokuへのデプロイをセットアップし、無料枠を使用してサンプルアプリを強化します。
9.1. pom.xmlを変更する
まず、このWeb Runner pluginをpom.xmlに追加する必要があります。
org.apache.maven.plugins
maven-dependency-plugin
2.3
package
copy
com.github.jsimone
webapp-runner
7.0.57.2
webapp-runner.jar
注– Web Runnerを使用してHerokuでアプリを起動します。
HerokuでPostgresqlを使用するので、ドライバーに依存する必要があります。
org.postgresql
postgresql
9.4-1201-jdbc41
9.2. Procfile
サーバー上で実行されるプロセスをProcfileで次のように定義する必要があります。
web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT target/*.war
9.3. Herokuアプリを作成する
プロジェクトからHerokuアプリを作成するには、次のようにします。
cd path_to_your_project
heroku login
heroku create
9.4. データベース構成
次へ–アプリのPostgresデータベースプロパティを使用してデータベースを構成する必要があります。
たとえば、persistence-prod.propertiesは次のとおりです。
## DataSource Configuration ##
jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://hostname:5432/databasename
jdbc.user=xxxxxxxxxxxxxx
jdbc.pass=xxxxxxxxxxxxxxxxx
## Hibernate Configuration ##
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.hbm2ddl.auto=update
Herokuダッシュボードからデータベースの詳細[ホスト名、データベース名、ユーザー、パスワード]を取得する必要があることに注意してください。
また、ほとんどの場合と同様に、キーワード「user」はreserved word in Postgresであるため、「User」エンティティテーブル名を変更する必要があります。
@Entity
@Table(name = "APP_USER")
public class User { .... }
9.5. コードをHeokuにプッシュ
では、コードをHerokuにプッシュしましょう。
git add .
git commit -m "init"
git push heroku master
10. 結論
ケーススタディのこの第4部では、焦点は小さいが重要な改善でした。 フォローしていると、これがどのように面白くて便利な小さなアプリになりつつあるかがわかります。