前言:
开发模式采用前后端分离,前端用angular(这里指的是angular2,不要和angularjs混淆了),后端采用springBoot,主要介绍下angular与后端接口调用问题。
思路:
其实官网都有调用,只是一些地方要注意到,而往往就是一些小细节或者小问题卡你半天,因此技术点无大小。
正题:
前端angular定义了一个服务文件,专门放置与后端接口交互的方法接口,方法接口中采用的是angular的 HttpClient 的get,put,post,delete方法 参数各异,但大多数第一个参数就是后端url,第二个参数视情况而定,详细的可以去angular的官网文档中去查看阅读,后面针对增、删、改、查会给出具体代码;
angular HttpClient官方参考API:Angular HttpClient API
后端采用springboot,搞技术的人都不陌生,唯一强调一点,也是困扰我半天的地方,就是因为前段会存在跨域问题,所以在后端的接口定义上要加上几个配置注释,此外接收参数时,参数上要加上@RequestBody 配置说明,否则参数实体对象接收为空
具体代码如下:
前段代码:
一,定义前段对象实体
export class UserInfo {
id: number;
userName: string;
password: string;
// public constructor(
// fields?: {
// id: number,
// userName: string,
// password: string
// }) {
// // tslint:disable-next-line:curly
// if (fields) Object.assign(this, fields);
// }
// public constructor(name: string) {
// this.userName = name;
// }
getFullName(): string {
return this.id + ' ' + this.userName;
}
}
二:定义前段接口调用类service.service.ts(为服务类,可用angular命令生成)
ng generate service service
然后填充service代码如下:
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {UserInfo} from './userInfo';
import {logger} from 'codelyzer/util/logger';
import {log} from 'util';
import {catchError} from 'rxjs/operators';
import {callHooks} from '@angular/core/src/render3/hooks';
const httpOptions = {
headers: new HttpHeaders({'content-Type': 'application/json'})
};
@Injectable({
providedIn: 'root'
})
export class ServiceService {
// private static METHOD_DELTE = 'DELETE';
// private static METHOD_POST = 'POST';
// private static METHOD_GET = 'GET';
// private static METHOD_PUT = 'PUT';
private serviceUrl = 'http://127.0.0.1:8080';
constructor(private httpClient: HttpClient) {
}
// 获取列表数据
getUserList(): Observable<UserInfo[]> {
return this.httpClient.get<UserInfo[]>(this.serviceUrl + '/findUserList');
}
// 获取单个数据
getOneUser(id: number): Observable<UserInfo> {
const params = new HttpParams({
fromString: 'id=' + id
});
const findhttpOptions = {
headers: new HttpHeaders({'content-Type': 'application/json'}),
params: params
};
return this.httpClient.get<UserInfo>(this.serviceUrl + '/findOneUser', findhttpOptions)
.pipe(catchError(this.handleError<UserInfo>('getOneUser id' + id)));
}
// 添加一个新用户
addUser(user: UserInfo): Observable<UserInfo> {
return this.httpClient.post<UserInfo>(this.serviceUrl + '/save', user, httpOptions)
.pipe(catchError(this.handleError<UserInfo>('addUser')));
}
// 删除一个用户
deleteUser(user: UserInfo | number): Observable<UserInfo> {
const id = typeof user === 'number' ? user : user.id;
const url = `${this.serviceUrl}/${id}`;
const delhttpOptions = {
headers: new HttpHeaders({'content-Type': 'application/json'}),
body: user
};
return this.httpClient.delete<UserInfo>(url, delhttpOptions)
.pipe(catchError(this.handleError<UserInfo>('deleteUser')));
}
// 更新数据
updateUser(user: UserInfo): Observable<any> {
return this.httpClient.put(this.serviceUrl + '/update', user, httpOptions)
.pipe(catchError(this.handleError('updateUser id=' + user.id)));
}
/**
* Handle Http operation that failed.
* Let the app continue.
* @param operation - name of the operation that failed
* @param result - optional value to return as the observable result
*/
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error(error); // log to console instead
// TODO: better job of transforming error for user consumption
log(`${operation} failed: ${error.message}`);
// Let the app keep running by returning an empty result.
return of(result as T);
};
}
}
三: 当然要用httClient,就必须在跟组件app.module.ts下导入:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {HttpClientModule} from '@angular/common/http';
import { UserInfoComponent } from './user-info/user-info.component';
import { AppRoutingModule } from './/app-routing.module';
import { UserInfoDetailComponent } from './user-info-detail/user-info-detail.component';
import {FormsModule} from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
UserInfoComponent,
UserInfoDetailComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
四:在使用组件中调用service中的各方法:
我的应用组件为user-info.component.ts
import {Component, OnInit} from '@angular/core';
import {UserInfo} from '../userInfo';
import {ServiceService} from '../service.service';
@Component({
selector: 'app-user-info',
templateUrl: './user-info.component.html',
styleUrls: ['./user-info.component.css']
})
export class UserInfoComponent implements OnInit {
results: string[]; // 返回结果 字符串数组
myUserList: UserInfo[]; // 人员列表
oneUser: UserInfo; // 单用户对象
rest: string; // 返回结果 字符串格式
constructor(private service: ServiceService) {
}
ngOnInit() {
this.findUserList();
}
// 查询用户列表
findUserList(): void {
this.service.getUserList().subscribe(data => this.myUserList = data);
}
// 增加用户
add(userName: string): void {
userName = userName.trim();
if (!userName) {
return;
}
this.service.addUser({userName} as UserInfo)
.subscribe(user => {
this.myUserList.push(user);
});
}
// 删除用户
delete(user: UserInfo): void {
this.myUserList = this.myUserList.filter(h => h !== user);
this.service.deleteUser(user).subscribe();
}
}
至此,前段代码基本完毕:
五:后端spring代码:
定义 UserInfo 实体对象
package com.sxsj.demo.baseInfo.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class UserInfo {
public UserInfo(String userName, String password) {
this.userName = userName;
this.password = password;
}
public UserInfo() {
}
@Id
@GeneratedValue
private Integer id;
private String userName;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
六,为解决跨域问题,添加CorsConfig.java类
package com.sxsj.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 对系统后台进行跨域访问进行配置
*/
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")// 1 设置访问源地址
.allowCredentials(true)// 2 设置访问源请求头
.allowedMethods("GET", "POST", "DELETE", "PUT") // 3 设置访问源请求方法
.maxAge(3600);
}
// @Bean
// public CorsFilter corsFilter() {
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
// return new CorsFilter(source);
// }
}
七:定义controller接口类 UserInfoController.java类
package com.sxsj.demo.baseInfo.controller;
import com.sxsj.demo.baseInfo.dto.UserInfoDto;
import com.sxsj.demo.baseInfo.entity.UserInfo;
import com.sxsj.demo.baseInfo.service.UserInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
//@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RestController
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
@GetMapping(value="/list")
public ModelAndView list(Map<String,Object> map){
List<UserInfo> list = this.userInfoService.findAlls();
map.put("userinfos",list);
return new ModelAndView("baseinfo/userInfo",map);
}
@GetMapping(value="/findOneUser")
public Object findOneUser(HttpServletRequest request,HttpServletResponse response){
String id = (String) request.getParameter("id");
UserInfo userInfo = this.userInfoService.findById(Integer.parseInt(id));
if(null != userInfo ){
return userInfo;
}
return null;
}
@CrossOrigin
@GetMapping(value="/findUserList")
public Object findUserList(HttpServletRequest request,HttpServletResponse response){
String name = (String)request.getParameter("_page");
System.out.println(">>>>>>>>>>>>>>>>>>"+name);
// response.setHeader("Access-Control-Allow-Origin","*");
List<UserInfo> list = this.userInfoService.findAlls();
return list;
}
// @CrossOrigin
@ResponseBody
@PostMapping(value="/save")
public UserInfo save(HttpServletResponse response, @RequestBody UserInfo userInfo){
// response.setHeader("Access-Control-Allow-Origin","*");
return this.userInfoService.save(userInfo);
}
// @CrossOrigin
@ResponseBody
@PutMapping(value="/update")
public UserInfo update(HttpServletResponse response, @RequestBody UserInfo userInfo){
// response.setHeader("Access-Control-Allow-Origin","*");
return this.userInfoService.save(userInfo);
}
@ResponseBody
@DeleteMapping
public void delete(HttpServletResponse response, @RequestBody UserInfo userInfo){
if(null == userInfo) return;
this.userInfoService.deleteById(userInfo.getId());
}
}
ok,后端后面的service接口就是基本的springboot Service层接口定义了,这里就不贴了。
以上就是angular和后端springboot 通过http请求的交互。