What does it take to go from server rendering to custom rendering? Why is Angular 2+ good and how to migrate to it? In this article, we will try to understand these issues and describe the migration process from server-side rendering technologies such as JSP to client-side rendering technologies using Angular .
Technologies used
Before starting the code, let's describe the entire stack of technologies used:
Spring Framework is a framework for the Java platform.
JSP - , , , . JSP : , (, HTML) JSP-. , Java- .
AngularJS Angular - JavaScript- Google . AngularJS JavaScript-, (SPA). 2009 . 2016 Angular 2. TypeScript AngularJS.
, Spring+JSP AngularJS. - SPA Angular.
?
Angular JSP AngularJS.
JSP Angular , ( ) . Angular . , ( , ). , .
, .
Angular
JSP- Angular . Angular CLI. Angular CLI - Angular-. , .
Angular CLI , :
npm install @angular/cli
Angular :
ng new < >
ng new ββ . Angular CLI "" .
JSP- , Java-, : http://www.springframework.org/tags, , http://java.sun.com/jsp/jstl/core. , , , . , . , , . , , . Spring Security, "/messages/*":
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/messages/*");
}
, , . .
, , . , , Angular . , - , -. , Angular CLI - Spring. Angular - , .
βproxy.conf.jsonβ -:
{
"/api": {
"target": "http://localhost:8099",
"secure": false,
"cookieDomainRewrite": "localhost",
"changeOrigin": true
}
}
package.json, , "start": "ng serve --proxy-config proxy.conf.json".
JSP Angular
Angular , . - , TypeScript, HTML CSS. JSP- , html, typescript css. . AngularJS Angular.
, ngOnInit , .
JSP- . .
<%
if (!SecurityUtils.hasRole(SecurityConstants.VIEW_USER)) {
response.sendRedirect("login.jsp");
}
%>
Angular , Guards. Guards .
guard- true, false. ( Boolean), (Observable<boolean> Promise<boolean>). VIEW_SETTINGS. hasPrivilege Observable<boolean>.
@Injectable({
providedIn: 'root'
})
export class SettingsGuard {
readonly SECURITY_CONSTANTS = SecurityConstants;
constructor(private router: Router,
private securityConstantService: SecurityConstantService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):
Observable<boolean|UrlTree> | Promise<boolean|UrlTree> | boolean|UrlTree {
return this.securityConstantService.hasPrivilege(this.SECURITY_CONSTANTS.VIEW_SETTINGS);
}
}
- , . HttpInterceptor, http- . 401 403 :
public handleError(err: HttpErrorResponse): Observable<any> {
if (err.url != null && (err.status === 401 || err.status === 403)) {
this.router.navigate(['/login']);
}
return throwError(err.error);
}
, , . RequestCache CachingInterceptor.
RequestCache - , , . "/", .
cache = new Map<string, RequestCacheEntry>();
get(req: HttpRequest<any>): HttpResponse<any> | undefined {
const url = req.url + req.body.key;
const cached = this.cache.get(url);
if (!cached) {
return undefined;
}
const isExpired = cached.lastRead < (Date.now() - maxAge);
return isExpired ? undefined : cached.response;
}
put(req: HttpRequest<any>, response: HttpResponse<any>): void {
const url = req.url + req.body.key;
const newEntry = { url, response, lastRead: Date.now() };
this.cache.set(url, newEntry);
const expired = Date.now() - maxAge;
this.cache.forEach(entry => {
if (entry.lastRead < expired) {
this.cache.delete(entry.url);
}
});
}
CachingInterceptor HttpInterceptor, , . , HttpInterceptor, intercept.
, ( isCacheable), , , . , Observable . , , sendRequest. .
intercept(req: HttpRequest<any>, next: HttpHandler) {
if (!isCacheable(req)) { return next.handle(req); }
const cachedResponse = this.cache.get(req);
if (req.headers.get('x-refresh')) {
const results$ = sendRequest(req, next, this.cache);
return cachedResponse ?
results$.pipe( startWith(cachedResponse) ) :
results$;
}
return cachedResponse ?
of(cachedResponse) : sendRequest(req, next, this.cache);
}
, Angular , . . . , . , .