我尝试用AngularJS+JavaEE搭建了一个类似于SIer的WEB应用程序(第一部分)
有一些人说要用AngularJS+JavaEE(JPA、JAX-RS)来替换在seasar2上实现的WEB应用程序!所以我创建了一个实际的示例来展示它会是什么样子。
作为一个只开发后端的人,结果只能以这种方式结束了。
这里是原始代码链接:
https://github.com/ko-aoki/angularJS_practice/tree/forQiita
我所参考的书籍如下。
-
- Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava (Programmer’s SELECTION)
- AngularJSアプリケーション開発ガイド
一旦开始实际制作后,只有书本上的信息远远不够,感觉很困难。
Oracle对JavaEE非常重视,但是从JavaEE6开始,特别是JPA的日本语信息明显不足。
功能概述
以大致的方式运行,实现以下功能。
-
- ログイン
-
- メニュー
-
- 条件検索画面(検索結果明細を表示)
-
- データ登録画面
- コード照会画面(ページ検索)
使用应用程序
-
- NetBeans8
-
- 業務だとeclipseを10年以上使用しているのですが、JavaEEならNetBeansかなと採用。
-
- 自動生成機能が強力でした。
-
- WebStorm8
-
- AngularJSのコード補完があったり。NetBeansも対応していたかな?
- まだ使いこなせてないです。。
文件夹结构
+—src // Java源代码
| \—java
| +—基础
| | \—实体
| +—实体
| +—实体类
| +—表单
| +—仓库
| +—资源
| +—服务
| \—工具
+—test // 测试源代码。包括karma等。
\—web
+—样式
+—数据
+—图片
+—图片
+—脚本
| +—控制器 // AngularJS控制器
| +—指令 // AngularJS指令
| +—服务 // AngularJS服务
| \—第三方库 // AngularJS,jQuery等库文件
+—分部 // AngularJS模板
+—模板 // AngularJS模板(指令用)
\—WEB-INF
设定文件(的那种东西)
JavaScript – JavaScript
- main.js
使用RequireJS时,如果文件增加,请在此处添加。
require.config({
paths: {
'jquery': 'vendor/jquery/jquery',
'jquery.treeview': 'vendor/jquery/jquery.treeview',
'angular': 'vendor/angular/angular',
'angularRoute': 'vendor/angular/angular-route',
'angularResource': 'vendor/angular/angular-resource',
'angularMocks': 'vendor/angular-mocks/angular-mocks',
'domReady': 'vendor/requirejs/domReady'
},
shim: {
'jquery' : {'exports' : 'jquery'},
'jquery.treeview' :['jquery'],
'angular' : {'exports' : 'angular'},
'angularRoute': ['angular'],
'angularResource': { deps:['angular'] },
'angularMocks': {
deps:['angular'],
'exports':'angular.mock'
}
}
});
require([
'angular',
'app',
'domReady',
//ファイルを追加したらここに追記
'services/dtoSrv',
'controllers/loginCtrl',
'controllers/menuCtrl',
'controllers/mntMstUserCtrl',
'controllers/mntMstUserRegCtrl',
'controllers/mntMstUserRegConfirmCtrl',
'controllers/codeDeptCtrl',
'directives/csngPage',
'directives/csngCodeDept'
],
function (angular, app, domReady) {
'use strict';
app.config(['$routeProvider',
function($routeProvider) {
//ルートの定義。画面を追加したらここで追記
$routeProvider.when('/login', {templateUrl: 'partials/login.html', controller: 'LoginCtrl'});
$routeProvider.when('/menu/:roleId', {templateUrl: 'partials/menu.html', controller: 'MenuCtrl'});
//中略
$routeProvider.otherwise({redirectTo: '/login'});
}
]);
domReady(function() {
angular.bootstrap(document, ['MyApp']);
$('html').addClass('ng-app: MyApp');
});
}
);
Java企业版
- persistence.xml
参考了寺田先生的文章,然后在NetBeans中进行自动生成。
实施
登录
当输入用户ID和密码后,点击”登录”按钮,系统将访问服务器并参阅用户主数据库,根据查询结果进行下一步页面跳转或输出错误信息。
AngularJS: 请将以下内容用中文进行改写,只需要一种选项:
AngularJS
创建模板文件和相应的控制器文件。
- login.html
<h1>ログイン</h1>
<ul>
<li ng-repeat="message in messages">
<p>{{message}}</p>
</li>
</ul>
<br>
<span>ユーザID :</span><input type="text" ng-model="loginUserId"/>
<br>
<span>パスワード:</span><input type="text" ng-model="password"/>
<br>
<button class="btn" ng-click="login()">ログイン</button>
- loginCtrl.js
在控制器文件中,通过JAX-RS进行访问,并根据结果输出错误或进行页面跳转。
通过$resource创建资源对象,并使用get方法访问服务器。
如果使用$location.path,则不会发生HTTP请求。
define(['controllers','angularResource'],
function(controllers) {
controllers.controller('LoginCtrl', ['$scope', '$http', '$location', '$resource',
function ($scope, $http, $location, $resource) {
$scope.login = function login() {
var login = $resource('webresources/login/:loginUserId,:password',
{
'loginUserId': '@loginUserId',
'password': '@password'
}
);
login.get(
{'loginUserId': $scope.loginUserId, 'password': $scope.password},
function (data) {
if (data.result === "error") {
$scope.messages = data.messages;
} else {
$location.path("menu/" + data.roleId);
}
}
);
};
}]);
});
JavaEE是一种用于开发企业级应用程序的编程语言和平台。
- LoginResource.java
AngularJS的资源类,用于访问。
根据@Path指定的请求URL格式,确定相应的类和方法。
当以’login で”webresources/login/ユーザ,パスワード”的形式请求loginCtrl.js时,
将执行login方法。
通过@Inject进行DI。
通过@Produces(“application/json”),将返回的Java对象转换为JSON格式。
@Path("login")
public class LoginResource {
@Inject
private LoginService loginService;
public LoginResource() {
}
@GET
@Path("{userId},{password}")
@Produces("application/json")
public LoginForm login(@PathParam("userId") String userId, @PathParam("password") String password) {
return loginService.login(userId, password);
}
}
- LoginServiceImpl.java
被资源类调用的服务类。
从转移现有Java应用的角度来看,我们决定在返回值中指定form类。
利用Repository类获取Entity类,并将其转录到Form类中。
public class LoginServiceImpl implements LoginService{
@Inject
private MstUserRepository mstUserRep;
public LoginForm login(String userId, String password) {
List<MstUser> rec = mstUserRep.findByUserId(userId);
LoginForm form = new LoginForm();
if (rec.isEmpty()) {
form.setMessages(Arrays.asList("ユーザが存在しません"));
form.setResult("error");
} else {
if (password.equals(rec.get(0).getPassword())) {
form.setRoleId(rec.get(0).getRoleId().getRoleId());
form.setResult("ok");
} else {
form.setMessages(Arrays.asList("パスワードが一致しません"));
form.setResult("error");
}
}
return form;
}
}
- MstUserRepositoryImpl.java
操作实体的存储库类。
老实说,我不太理解它与DAO的区别。
@PersistenceContext 指定了 persistence-unit。这里看起来可以进行共享化。
findByUserId 使用了 NamedQuery。
public class MstUserRepositoryImpl implements MstUserRepository{
@PersistenceContext(name = "common-app-javaee7PU")
private EntityManager em;
/**
* ユーザIDでユーザを検索します.
* @param userId
* @return
*/
@Override
public List<MstUser> findByUserId(String userId) {
Query query = em.createNamedQuery("MstUser.findByUserId", MstUser.class);
query.setParameter("userId", userId);
List<MstUser> rec = query.getResultList();
return rec;
}
//中略
/**
* ユーザ情報を更新します.
* @param user
*/
@Override
@Transactional(Transactional.TxType.REQUIRED)
public void update(MstUser user) {
em.merge(user);
}
}
- MstUser.java
这个也可以在NetBeans中指定表格并自动生成。
总结
在旧有的Java框架中,JSP+动作类的实现部分可以用AngularJS来替代。
实际写起来感觉比以前更清晰地分离了前端和后端逻辑。JSP渲染页面需要花费一定的时间,所以去掉这个可以说是一个很大的进步。
JAX-RS可以只通过注解就能完成想做的事情。想起以前编写的代码,不禁流连忘返。
因为之前用的是MyBatis之类的基于原生SQL的框架,对JPA的理解相当困难。
继续下去