Javaで自転車を発明する-フレームワーク(DI、ORM、MVCなど)を書く

それはすべて、Java Commonライブラリを書くことにしたという事実から始まりました。 スタックオーバーフローの一般的なタスクでは、3〜5〜10行のコードで解決策が頻繁に発生します。 自分をプロジェクトにコピーするのはうんざりです。 これを別のライブラリに配置することにしました。このライブラリはオープンソースにして、現在および将来のプロジェクトで使用できます。 もちろん、Google GuavaやApache Commonsのような優れたものもありますが、これらも私の仕事で使用していますが、それらは非常に「正確」で柔軟性があり、複数行のコードに変換されません。



その結果、私の自由な時間の夜の自宅で、私は次の1週間の指示をカバーしました:スリープ/遅延/一時停止、ベンチマーク用タイマー、ランダム範囲ジェネレーター、ファイル操作、タスク/スレッド、リフレクション、JSON、URL、ロギング、ストリング 私は自分のプロジェクトで標準ソリューションのコピー&ペーストを探し、ライブラリにソリューションを書きました。 ここでも、TDDアプローチを使用してライブラリを開発しました。 最初に、存在しないクラスとメソッドのテストを作成し、次にテストを緑色に変えるようにコードを実装します。 それは2つの問題を解決します:最初に、クラスとそのメソッドを実装する前に便利に使用することを試みます。2番目に、将来落ちる可能性のあるテストがまだあります。



さらにもっと。 私や他の多くの人と同様に、通常はSpring / JBossを使用して分析を開始し、レガシーと機会の広がりが事態を複雑にしていることに気付きました。 単純化された典型的な依存性注入を実装できます。 すぐに言ってやった。 ライブラリDIフレームワークに追加されました。 私の友人は私の実装を見て、Springが単に非現実的であるかを理解するために、継承とラッパーの完全な錫があり、実装の最初のレベルですべてを見ることができ、すべてが明確であると言いました。 彼らは、アノテーションなどを扱う方法に興味がありました。



DIフレームワークを実装したら、もう少し本格的なEnterprise Serverになるということを考えました。 ORMと、MVC、REST、およびセキュリティを備えたWebサーバーを追加することは残っています。 いわば、最高の伝統のすべてです。 そして引きずられた。 仕事の後の別の週、妻との口論で、Simplified Enterprise Serverになりました。 私が書いたように、私はJavaEE標準に準拠していませんでした。 私自身は、Spring Boot、Spring Data、JPA 2.0、Spring MVC、Spring Rest、Spring Securityを使用しています。 その前に、私はJBossでプロジェクトを行いました、いわばJEEの反対側を見ました。 しかし、このテーマのすべての汎用性と柔軟性はもちろんです。 しかし、JEEスタイルのプロトタイプをすぐに作成する必要がある場合、または本格的なJavaプロジェクトのコーディング方法を学ぶ必要がある場合は、Spring、Hibernateなどの世界に飛び込んでください。 長く骨の折れる。 唯一の選択肢はSpring Bootですが、実際には隠れていることがたくさんあります.Springがボンネットの下でどのように機能するのかわからない場合は、ゆっくりと動きます。左または右へのステップは詳細の完全なダイビングです...



その結果、githubフレームワークのコードgithub.com/evgenyigumnov/common



github.com/evgenyigumnov/example githubでこのフレームワークを使用するWebサービスの例およびオンラインで見ることもできますjava.igumnov.com:8181ユーザー:demoパスワード:demo



構造例:

./: pom.xml ./javascript: user.js ./pages: index.html layout.html login.html ./sql: 1.sql ./src/main/java/com/igumnov/common/example: App.java ExampleUser.java
      
      







pom.xml

  <dependencies> <!--    --> <dependency> <groupId>com.igumnov</groupId> <artifactId>common</artifactId> <version>3.15</version> </dependency> <!--   --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.187</version> </dependency> <!--  Bootstrap, AnglularJS    webjars  --> <dependency> <groupId>org.webjars</groupId> <artifactId>angular-ui-bootstrap</artifactId> <version>0.12.0</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>angularjs</artifactId> <version>1.3.8</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.1</version> </dependency> </dependencies>
      
      







App.java

 public class App { public static void main(String[] args) throws Exception { ORM.connectionPool("org.h2.Driver", "jdbc:h2:mem:test", "SA", "", 1, 3); //      ( 3 ) ORM.applyDDL("sql"); //             WebServer.init("localhost", 8181); //    - WebServer.security("/login", "/login", "/logout"); //           URL- WebServer.addRestrictRule("/*", new String[]{"user_role"}); //        user_role WebServer.addAllowRule("/static/*"); //        WebServer.addClassPathHandler("/static", "META-INF/resources/webjars"); //        classpath  webjars WebServer.addAllowRule("/js/*"); //       Java Script- WebServer.addStaticContentHandler("/js", "javascript"); //         Java Script WebServer.addTemplates("pages",0); //          //     "/",        ,    index.html WebServer.addController("/", (request, model) -> { model.put("time", new Date()); return "index"; }); //     "/login",  ,    login.html WebServer.addController("/login", (request, model) -> { return "login"; }); //  REST-   "/rest/user"      POST/PUT  JSON-  ExampleUser.class WebServer.addRestController("/rest/user", ExampleUser.class, (request, postObj) -> { switch (request.getMethod()) { case (WebServer.METHOD_GET): //  GET  ArrayList<Object> users; try { users = ORM.findAll(ExampleUser.class); //    } catch (Exception e) { throw new WebServerException(e.getMessage()); //  ,     JSON } return users; //        JSON case (WebServer.METHOD_POST): //  POST  ExampleUser ret = null; try { ret = (ExampleUser) ORM.insert(postObj); //     } catch (Exception e) { throw new WebServerException(e.getMessage()); } return ret; //          JSON case (WebServer.METHOD_DELETE): //  DELETE  ExampleUser user; try { user = (ExampleUser) ORM.findOne(ExampleUser.class, request.getParameter("userName")); //     if(user.getUserName().equals("demo")) { //   demo    throw new WebServerException("You cant delete user demo"); } else { ORM.delete(user); //     delete- } } catch (Exception e) { throw new WebServerException(e.getMessage()); //  ,     JSON } return user; //  JSON ,        default: throw new WebServerException("Unsupported method"); //      ,  PUT   } }); ArrayList<Object> users = ORM.findAll(ExampleUser.class); //      if (users.size() == 0) { //      ExampleUser user = new ExampleUser(); user.setUserName("demo"); user.setUserPassword("demo"); ORM.insert(user); //  demo/demo    WebServer.addUser("demo", "demo", new String[]{"user_role"}); //  -    demo/demo   user_role } users.stream().forEach((user) -> { //       ExampleUser u = (ExampleUser) user; WebServer.addUser(u.getUserName(), u.getUserPassword(), new String[]{"user_role"}); //  -      user_role }); WebServer.start(); //             Exception,   - :) } }
      
      







ExampleUser.java

 //     JSON          public class ExampleUser { @Id(autoIncremental = false) //  ORM     Primary Key     insert    private String userName; private String userPassword; ... }
      
      







1.sql

 #         ORM   ExampleUser.class CREATE TABLE ExampleUser (userName VARCHAR(255) PRIMARY KEY, userPassword VARCHAR(255))
      
      







login.html

 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      layout  layout.html --> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"> <body> <!--         layout.html --> <div layout:fragment="content"> <form name="form" action="/j_security_check" method="POST"> <div class="modal-header"> <h3 class="modal-title">Login</h3> </div> <div class="modal-body"> <div class="form-group"> <input type="text" name="j_username" class="form-control" value="" placeholder="Login"/> </div> <div class="form-group"> <input type="password" name="j_password" class="form-control" placeholder="Password"/> </div> <div class="form-group"> <button type="submit" id="login" class="btn btn-primary">OK</button> </div> </div> </form> </div> </body> </html>
      
      







index.html

 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      layout  layout.html --> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"> <body> <!--         layout.html --> <div layout:fragment="content"> <!--     AngularJS--> <script src="/js/user.js"></script> <h1 th:text="${time}"></h1> //       <!--      UserCtrl --> <div ng-controller="UserCtrl"> <table class="table"> <thead> <tr> <th>Name</th> <th>Password</th> <th></th> </tr> </thead> <tbody> <!--      --> <tr ng-repeat="user in users"> <td>{{user.userName}}</td> <td>{{user.userPassword}}</td> <!--            --> <td><a href="#"><span class="glyphicon glyphicon-remove" tooltip="Delete" ng-click="deleteUser(user)"/></a></td> </tr> </tbody> </table> <div ng-model="user"> <!--    --> <div class="form-group"> <input type="text" class="form-control" ng-model="user.userName" placeholder="Login"/> </div> <div class="form-group"> <input type="password" class="form-control" ng-model="user.userPassword" placeholder="Password"/> </div> <div class="form-group"> <!--           --> <button class="btn btn-primary" ng-click="addUser(user)">Add</button> </div> </div> </div> </div> </body> </html>
      
      







layout.html

 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      AngularJS --> <html ng-app="com.igumnov.common.example"> <head> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/3.3.1/css/bootstrap.min.css" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <script src="/static/angularjs/1.3.8/angular.min.js"></script> <script src="/static/angularjs/1.3.8/angular-resource.min.js"></script> <script src="/static/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script> <div class="container"> <!--      --> <div layout:fragment="content"></div> </div> </body> </html>
      
      







user.js

 angular.module('com.igumnov.common.example', ['ui.bootstrap', 'ngResource']) .factory('User', ['$resource', function ($resource) { //  REST- User return $resource('/rest/user', {}, { list: { //   method: 'GET', cache: false, isArray: true //    }, add: { //   method: 'POST', cache: false, isArray: false //     }, delete: { //   method: 'DELETE', cache: false, isArray: false //     } }); }]) .controller('UserCtrl', function ($scope, User) { //    UserCtrl $scope.users = User.list({}); //       $scope.addUser = function (user) { //    User.add({},user,function (data) { //  REST- $scope.users = User.list({}); //   ,    }, function (err) { alert(err.data.message); //   ,   }); } $scope.deleteUser = function (user) { //    User.delete({"userName" : user.userName},user,function (data) { //  REST- $scope.users = User.list({}); //   ,    }, function (err) { alert(err.data.message); //   ,   }); } });
      
      







結論として、ライブラリコードを改善するための批判や提案を歓迎します。 私自身は、ライブラリを作成してクロージャー/ラムダを使用する際に、脳をこねることで利益を得ました。 商用製品を書くのは退屈な場合があります。独自の宇宙船を作成したい場合があります。 おでこをフォークして、自分のニーズに合わせて自分で修正してください。 修正は非常に簡単で簡単です。 ライブラリに改善が加えられるように、プルリクエストを送信していただければ幸いです。 私は個人的にそれらを十分に迅速に確認し、受け入れることに決めています。 私はただの熱狂的なプログラマーです。 私はコーディングが大好きです!



PSはい、はい、javadocを作成し、それを使用してプルリクエストを送信するのは好きではありません。各メソッドがそれを行うことはコードによって非常に明確になりました...



All Articles