问题
I'd like to have a variable called _contextPath
, which is a Javascript evaluated variable in a JSP, and which is currently available in systemjs.config.js
-- I'm trying to have this _contextPath
variable available in a Typescript Service.
I'd like to know if the _contextPath
variable can be passed onto the Typescript Service called job.service.ts
Here is my folder structure:
├── scripts
│ └── mec-irs
│ ├── app
| | ├── app.component.ts
| | ├── app.module.ts
| | ├── app.routes.ts
| | └── jobs
| | ├── job.ts
| | ├── job.routes.ts
| | └── job.service.ts
│ ├── db.json
│ ├── GruntFile.js
│ ├── index.html
│ ├── node
│ ├── node_modules
│ ├── package.json
│ ├── style.css
│ ├── systemjs.config.js
│ ├── tsconfig.json
│ ├── typings
│ └── typings.json
├── views
│ ├── mec.jsp
The mec.jsp
gets the context via Javascript call and stores it in a variable called _contextPath:
<html>
<head>
<title>MEC IRS</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script>var _contextPath = "${pageContext.request.contextPath}";</script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="..<%=request.getContextPath()%>/scripts/mec-irs/style.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="..<%=request.getContextPath()%>/scripts/mec-irs/node_modules/core-js/client/shim.min.js"></script>
<script src="..<%=request.getContextPath()%>/scripts/mec-irs/node_modules/zone.js/dist/zone.js"></script>
<script src="..<%=request.getContextPath()%>/scripts/mec-irs/node_modules/reflect-metadata/Reflect.js"></script>
<script src="..<%=request.getContextPath()%>/scripts/mec-irs/node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="..<%=request.getContextPath()%>/scripts/mec-irs/systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
The _contextPath
is used in systemjs.config.js
:
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': _contextPath + '/scripts/mec-irs/node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: _contextPath + '/scripts/mec-irs/app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
}
}
});
})(this);
The Java web application context is hardcoded though in job.service.ts
as mec
. I'd like to know how to pass the _contextPath
to this Typescript Service called job.service.ts
please. As seen below the context mec
is hardcoded as /mec/admin/irs/jobs/
, which is a web service endpoint:
import {Injectable, Inject} from '@angular/core';
import {Http, Headers} from '@angular/http';
import 'rxjs/add/operator/map';
// Decorator to tell Angular that this class can be injected as a service to another class
@Injectable()
export class JobService {
// Class constructor with Jsonp injected
constructor( @Inject (Http)private http:Http) { }
// Base URI for Spring Batch Admin
private jobsUrl = '/batch/';
//TODO wish not to have hardcoded context, like below
//private mecUrl = '/' + _contextPath + '/admin/irs/jobs/';
private mecUrl = '/mec/admin/irs/jobs/';
// Stop Spring Batch Job by its name
stopJobByName(name: string) {
const endPoint = name + '/stopIrsJobPoller';
return this.http.get(this.mecUrl + endPoint)
.map(res => res.json());
}
.
.
.
回答1:
You need something that will run at the application initialization and get your server side settings. Here is how I am doing this.
Create a class to store your server side configuration:
export class AppConfig {
public ContextPath: string;
};
Create a service to get your back-end configuration from your JSP:
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { AppConfig } from './app.config';
@Injectable()
export class ConfigService {
private _config: AppConfig;
constructor(private http: Http, private config: AppConfig) {
}
public Load(): Promise<AppConfig> {
return new Promise((resolve) => {
this.http.get('./views/mec.jspn').map(res=>res.json())
.subscribe((config: AppConfig) => {
this._config = data;
resolve(this._config);
}, (error: any) => {
this._config = new AppConfig();
resolve(this._config);
});
});
}
public Get(key: any): any {
return this._config[key];
}
}
Then boostrap it in your app module initialization by providing your ConfigService as the provider for the APP_INITIALIZER:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Http, HttpModule } from '@angular/http';
import { APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ConfigService } from './shared/services/index';
import { AppConfig } from './app.config';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) => () => configService.Load(),
deps: [ConfigService, Http, AppConfig],
multi: true
},
ConfigService,
AppConfig
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Then simply using it by injecting the ConfigService in any other service:
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Injectable } from '@angular/core';
import { ConfigService } from './config.service';
@Injectable()
export class AppService {
constructor(
private _http: Http,
private _config: ConfigService
) {
console.log(_config.Get('ContextPath'));
}
}
来源:https://stackoverflow.com/questions/40567158/pass-web-application-context-to-angular2-service