一。 http协议简介
http协议是互联网超文本传输协议 ,互联网程序基于http协议开发 ,基于http协议的架构风格rest最近风行 ,rest架构风格将
互联网操作的任意事物都解释为资源 针对资源拥有不同的操作 比如 put(修改)get(获取) post(新增) delete(删除)
以下具体实现参考:https://angular.io/tutorial/toh-pt6#httpclientget-returns-response-data
二。httpapi调用实例
ANGUARJS2使用 rxjs(异步)作为http的api 关于rxjs可以参考(https://cn.rx.js.org/manual/overview.html)
RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和受 [Array#extras] 启发的操作符 (map、filter、reduce、every, 等等),
这些数组操作符可以把异步事件作为集合来处理。结合了 观察者模式、迭代器模式 和 使用集合的函数式编程,以满足以一种理想方式来管理事件序列所需要的一切。
在 RxJS 中用来解决异步事件管理的的基本概念是:
- Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。
- Observer (观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。
- Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。
- Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、concat、flatMap 等这样的操作符来处理集合。
- Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。
- Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。
1》 使用springboot搭建一个rest风格的操作hero的控制层
创建springboot项目 t添加main方法
package cn.ps;
import org.apache.solr.client.solrj.SolrClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.solr.core.SolrTemplate;
@SpringBootApplication
public class SolrMain {
public static void main(String[] args) {
SpringApplication.run(SolrMain.class, args);
}
}
创建 允许跨域访问的配置类
package cn.ps;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 配置cors 允许跨域调用
* @author Administrator
*
*/
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
添加Hero实体类
package cn.ps.controller;
public class Hero {
private Integer id;
private String name;
public Hero() {
super();
}
public Hero(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
添加rest风格的控制层
package cn.ps.controller;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import cn.ps.dao.NewDao;
@RestController
public class HttpTestController {
@Autowired
private SolrTemplate solrTemplate;
@Autowired
private NewDao newDao;
static List<Hero> heros=new ArrayList<Hero>();
static {
heros.add(new Hero(1, "zs"));
heros.add(new Hero(2, "ls"));
heros.add(new Hero(3, "ww"));
heros.add(new Hero(4, "zl"));
heros.add(new Hero(5, "xe"));
}
@GetMapping("/query")
public Iterable<Hero> query(String name,Integer rows) {
if(rows==null) {
rows=10;
}
List<Hero> mheros=new ArrayList<Hero>();
if(!StringUtils.isNotEmpty(name)) {
return heros.subList(0, rows<=heros.size()-1?rows:heros.size()-1);
}
heros.forEach(hero -> {
if(hero.getName().equals(name)) {
mheros.add(hero);
}
});
return mheros.subList(0, rows);
}
@GetMapping("/hero/{id}")
public Hero findById(@PathVariable Integer id) {
List<Hero> mheros=new ArrayList<Hero>();
heros.forEach(hero -> {
if(hero.getId().equals(id)) {
mheros.add(hero);
}
});
return mheros.get(0);
}
@DeleteMapping("/hero/{id}")
public int deleteById(@PathVariable Integer id) {
heros.remove(findById(id));
return 1;
}
@PutMapping("/hero/{id}")
public int updateById(@PathVariable Integer id,@RequestBody Hero hero) {
Hero he = findById(id);
he.setName(hero.getName());
return 1;
}
@PostMapping("/hero")
public int saveHero(@RequestBody Hero hero) {
heros.add(hero);
return 1;
}
}
application.yml配置端口
server:
port: 7888
2》 修改英雄获取数据方式
修改helloservice 将获取数据的方式修改为远程调用(注意要引入rxjs和htttpclient和httpheaders)
import { Injectable } from '@angular/core';
import { Hero } from './heroes/hero';
import { HttpClient, HttpHeaders} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class HeroService {
/**
* 创建一个观察者 观察这个路径获取的数据
*/
myurl:string="http://localhost:7888";
getHeroes():Observable<Hero[]>{
return this.http.get<Hero[]>(this.myurl+"/query");
}
getTopHeroes():Observable<Hero[]>{
return this.http.get<Hero[]>(this.myurl+"/query?rows=3");
}
getHeroById(id:number):Observable<Hero>{
return this.http.get<Hero>(`${this.myurl}/hero/${id}`);
}
saveHero(hero:Hero):Observable<number>{
return this.http.post<number>(`${this.myurl}/hero`,hero);
}
updateHero(hero:Hero):Observable<number>{
return this.http.put<number>(`${this.myurl}/hero/${hero.id}`,hero);
}
deleteHero(id:number):Observable<number>{
return this.http.delete<number>(`${this.myurl}/hero/${id}`);
}
constructor(private http: HttpClient) { }
}
在app.module.ts中导入 HttpClientModule 如可以装配HttpClient类
imports: [
BrowserModule,FormsModule, AppRoutingModule,HttpClientModule
],
分为修改相应的控件 订阅观察者 回调获取数据并写入到控件属性中
英雄列表 (初始化进入获取所有数据)【heroes.component.ts】
ngOnInit() {
let curCom=this;
//订阅这个观察者 如果有数据返回 自动回调
this.helloService.getHeroes().subscribe((value:Hero[])=>{
curCom.heros=value;
});
}
仪表盘 (初始化进入获取前几条数据)【dashboard.component.ts】
ngOnInit() {
let cthis=this;
this.h.getTopHeroes().subscribe((value:Hero[])=>{
cthis.topHeros=value;
});
}
详情页(初始化根据获取的id 来获取数据)【herodetail.component.ts】
ngOnInit() {
let id:number=parseInt(this.route.snapshot.paramMap.get("id"));
let cthis=this;
this.heroService.getHeroById(id).subscribe((v:Hero)=>{
cthis.selectedHero=v;
});
}
详情页添加一个返回按钮 可以返回到之前页面 (herodetail.component.html)
<button (click)="clickReturn()">返回</button>
在模型中 引入((herodetail.component.ts))
import { Location } from '@angular/common';
构造方法中注入 Location服务
constructor(
private loc:Location,
private route: ActivatedRoute,
private heroService:HeroService) { }
添加调用方法
clickReturn(){
this.loc.back();
}
添加一个修改按钮用于保存 (herodetail.component.html)
<button (click)="saveHero()">保存</button>
添加保存的方法
saveHero(){
let cthis=this;
this.heroService.updateHero(this.selectedHero).subscribe((v:number)=>{
this.loc.back();
});
}
在列表页添加一个删除按钮(heroes.component.html)
<li *ngFor="let hero of heros">
<span class="badge">{{hero.id}}</span> <a routerLink="/detail/{{hero.id}}">{{hero.name}}</a> <a style="color:red" (click)="deleteHero(hero.id)">X</a>
</li>
在(heroes.component.ts)添加删除的事件
deleteHero(id:number){
let curCom=this;
this.helloService.deleteHero(id).subscribe((r:number)=>{
//订阅这个观察者 如果有数据返回 自动回调
this.helloService.getHeroes().subscribe((value:Hero[])=>{
curCom.heros=value;
});
});
}
最后运行最终效果是
437

被折叠的 条评论
为什么被折叠?



