Iris实现reponse拦截返回客户端消息

CloudCompare 二次开发(17)——点云添加均匀分布的随机噪声 使用CloudCompare编程实现点云添加随机噪声。 阅读详情

基本思路要求

2019/3/22 22:54晚间终于走通了大致的拦截流程。

项目需求,由于项目国际化需要,本公司所有系统翻译配置信息使用集中集群方式配置在apollo配置中心里面,最好的方式当然是吧所有的状态码都统一在路由层处理,但是同事实测nginx+lua解析服务返回json严重影响路由效率,因此java项目和go项目都统一使用自身拦截器处理,降低业务层逻辑的耦合。

java spirng boot项目的拦截器很丰富,也很容易实现,问题是go使用的这个框架iris查看源码所有的返回客户端的消息直接io.write写回去,并且其本身并没有提供responseHand的相关接口。因此处理参考文章末尾写了一半的源码解析,只能自己再别写边改。

思路如下:

返回客户端的数据主要有write,wrietString,JSON,JSONP,这几种类型,当然还有文件留之类的的,这里我们并不考虑此内容,本文也不做拦截。
熟悉源码之后可以发现,整个底层都是使用go自身的http.server和io实现的,只是在上面包装了一层,我们这里也只着重关注包装的router和context这两个类和方法,它们才是http交互的关键。因为http.Hander接口它赋值的是app.Router所以Route是进行请求和回写客户端的关键。所有的htttp请求都会使用router.mainHandler进行处理,该方法会通过HandleRequest(ctx)找到系统启动时注册的url和对应的处理方法名,使用该方法处理。

router.mainHandler = func(w http.ResponseWriter, r *http.Request) {
		ctx := cPool.Acquire(w, r)
		router.requestHandler.HandleRequest(ctx) //主要http请求入口
		cPool.Release(ctx)
	}

参数ctx则附带了大量http请求的url,参数等上下文信息,同时也是通过url找到对应处理方法后的主要入口ctx.Do(n.Handlers)

n := t.search(path, ctx.Params())
		if n != nil {
			ctx.SetCurrentRouteName(n.RouteName)
			ctx.Do(n.Handlers) //调用对应的方法进行处理
			// found
			return
		}

看到这里你应该明白了,所有的Controler中都会带上它的值contex,当然也包括上面说的给客户的回写消息,主要靠的也是它的实现接口,通过每个回写的方法拦截器中回调我们自己实现的具体拦截业务即可起到拦截内容后返回给它们继续后续处理的问题。而我们自己实现的具体拦截器当然最好是统一一个地方处理,在contex中各个write,JSON等方法统一处理即可,这样改写代码很少便可以实现拦截。

而go语言可以使用反射实现方法回调,因此实现起来还是很简单的。

http.server
Handler:{ServeHTTP(ResponseWriter, *Request)}这里既是实现了该接口的Application.Router

Application
*router.APIBuilder
*router.Router 实现了http.Handler接口
ContextPool *context.Pool 里面存放系统变量

新建 (route,Usercontroller)
ControllerActivator
router: url methond(fullpack,name)
value:

未完待续,后面我会加上更多内容:

本文作者:bamboo
email:zjcjava@163.com

具体修改方法

修改route.go方法

type Router struct {
	MyHand interface{} // 新增自定义字段
}


// the important
	router.mainHandler = func(w http.ResponseWriter, r *http.Request) {
		ctx := cPool.Acquire(w, r)
		ctx.ResponseHandler(router.MyHand)//添加我的拦截器
		router.requestHandler.HandleRequest(ctx)
		cPool.Release(ctx)
	}

修改context.go方法

type Context interface {


	ResponseHandler(o interface{})//给context赋值方法
}


type context struct {

	//新增自定义拦截器字段
	HandResponseWriter interface{}
}

// 实现该接口
func (ctx *context) ResponseHandler(o interface{}) {
	ctx.HandResponseWriter =  o
}

// 自定义拦截器调用该自定义字段,通过方法名反射找到方法
// ResponseWriter returns an http.ResponseWriter compatible response writer, as expected.
func (ctx *context) HandResponse(str string) string {

	fmt.Println("----------HandResponse拦截START-----------------------------")

	if ctx.HandResponseWriter!=nil {
		//ctx.HandResponseWriter.HandResponseWriter(str)
		o := ctx.HandResponseWriter
		t := reflect.ValueOf(o)         //反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息
		mv := t.MethodByName("HandResponseWriter")
		args := []reflect.Value{reflect.ValueOf(str)}
		rs :=mv.Call(args)
		str =rs[0].Interface().(string)

	}
	fmt.Println(str)
	fmt.Println("----------HandResponse拦截END-----------------------------")


	return str
}

//使用IO之前先调用拦截方法

func (ctx *context) Write(rawBody []byte) (int, error) {
	rawBody = []byte(ctx.HandResponse(string(rawBody)))
	return ctx.writer.Write(rawBody)
}

// Writef formats according to a format specifier and writes to the response.
//
// Returns the number of bytes written and any write error encountered.
func (ctx *context) Writef(format string, a ...interface{}) (n int, err error) {
	return ctx.writer.Writef(format, a...)
}

// WriteString writes a simple string to the response.
//
// Returns the number of bytes written and any write error encountered.
func (ctx *context) WriteString(body string) (n int, err error) {
	body = ctx.HandResponse(body)
	return ctx.writer.WriteString(body)
}



// JSON marshals the given interface object and writes the JSON response to the client.
func (ctx *context) JSON(v interface{}, opts ...JSON) (n int, err error) {
	options := DefaultJSONOptions

	if len(opts) > 0 {
		options = opts[0]
	}

	ctx.ContentType(ContentJSONHeaderValue)

	if options.StreamingJSON {
		if ctx.shouldOptimize() {
			var jsoniterConfig = jsoniter.Config{
				EscapeHTML:    !options.UnescapeHTML,
				IndentionStep: 4,
			}.Froze()
			enc := jsoniterConfig.NewEncoder(ctx.writer)
			err = enc.Encode(v)
		} else {
			enc := json.NewEncoder(ctx.writer)
			enc.SetEscapeHTML(!options.UnescapeHTML)
			enc.SetIndent(options.Prefix, options.Indent)
			err = enc.Encode(v)
		}

		if err != nil {
			ctx.StatusCode(http.StatusInternalServerError) // it handles the fallback to normal mode here which also removes the gzip headers.
			return 0, err
		}
		return ctx.writer.Written(), err
	}
	jsonStr, err := json.Marshal(v)
	if err != nil {
		fmt.Println("json err: ", err)
	}
	
	//转成json字符串 调用拦截方法
	 str :=ctx.HandResponse(string(jsonStr));
	json.Unmarshal([]byte(str), v) // 调用完成解析成原对象中
	
	n, err = WriteJSON(ctx.writer, v, options, ctx.shouldOptimize())
	if err != nil {
		ctx.StatusCode(http.StatusInternalServerError)
		return 0, err
	}

	return n, err
}

使用

package routers

import "fmt"

type  MyHand struct {

}



func (ctx MyHand) HandResponseWriter(str string) string {

	fmt.Println("----------MyHand-----------------------------")
	fmt.Println(str)

	// 检查字符串是否符合基本的json格式
	if( strings.HasPrefix(str, "{") && strings.HasSuffix(str, "}")){
		// 字符串转JSON
		var obj interface{}
		err := json.Unmarshal([]byte(str), &obj)
		if err != nil {
			fmt.Println(err)
		}

		objMap := obj.(map[string]interface{}) //转成Map

		code:=objMap["code"]

		fmt.Println("状态码是:",code)

		json, err := json.Marshal(objMap)// 转回JSON
		if err != nil {
			fmt.Println("json err: ", err)
		}

		//str=`{"code":"0000","msg":"失败","data":{"stat":"bamboo"}}`
		str=string(json)

	}


	fmt.Println(str)
	fmt.Println("----------MyHand-----------------------------")

	return  str
}

给app.Router.MyHand赋值

myHand := MyHand{}
	app.Router.MyHand=myHand

参考资料

在这里插入图片描述

Iris框架源码阅读和分析
https://www.cnblogs.com/rabbix/p/10332845.html

【C++项目】从零实现RPC框架「三」:项⽬抽象层实现 本文详细介绍了如何从零实现一个 C++ RPC(远程过程调用)框架,包括通信抽象、消息抽象、通信实现、以及消息分发器的实现。通过系统化的代码示例,展示了如何构建一个高效、灵活且可扩展的 RPC 框架。 阅读详情

相关推荐

手机拍照对焦快准狠的秘密:一文看懂PDAF、Dual Pixel和Super PD的区别

本文深入解析手机拍照中的三种主流相位检测自动对焦(PDAF)技术:Shield Pixel、Super PD和Dual Pixel。通过对比它们的原理、优缺点及实际表现,帮助读者理解不同技术的对焦速度、暗光表现和画质影响,从而做出更明智的购机选择。

weixin_26985923的博客 486

SpringMVC学习

SpringMVC项目配置步骤 (1)add Framework support… 选中web项目 (2)配置tomcat服务器,添加一个artifact (3)WEB-INF下新建lib目录放入相关jar包 (4)加载jar包:Project Structure -> Libraries -> 加一个lib选中项目目录下对应lib位置(记得选中对应项目) (5)在src下粘贴springmvc.xml文件,修改其中需要扫描的包(属性base-package) (6)在web -> WEB

qq_44296442的博客 136

软考软件评测师备考避坑指南:过来人告诉你这5个章节最容易丢分(附2024最新考纲解析)

本文为软考软件评测师考生提供备考避坑指南,深度解析5个高频失分章节,包括标准化与信息化基础、中间件技术、软件测试模型、白盒测试覆盖准则和性能测试指标。文章结合2024最新考纲,分享实战技巧和记忆口诀,帮助考生精准打击失分重灾区,提升备考效率。

weixin_29223603的博客 467

附:IRIS JSON使用示例

IRIS JSON使用示例

m0_62389521的博客 254

活用QueryWrapper与@Select注解,构建MybatisPlus动态多表查询方案

本文深入探讨了如何结合MybatisPlus的QueryWrapper与@Select注解,构建高效灵活的动态多表关联查询方案。通过解析${ew.customSqlSegment}占位符机制,并设计通用的Service层封装,解决了复杂条件下多表查询的SQL拼接难题,显著提升了后台管理系统列表查询的开发效率与可维护性。

weixin_29291069的博客 270

S32K144 ADC硬件触发实战:PDB模块配置与DMA传输全流程解析

本文详细解析了S32K144微控制器中ADC硬件触发的全流程实现。通过配置PDB模块产生精确的定时触发信号,并联动DMA实现转换数据的自动搬运,构建了一个无需CPU干预的高效、低抖动数据采集系统。文章深入讲解了时钟配置、模块初始化、DMA引擎搭建及实战调试技巧,为汽车电子和工业控制应用提供了可靠的解决方案。

weixin_29174141的博客 225

web框架:Iris快速入门

web框架:Iris快速入门

weixin_45565886的博客 3934

halcon C++编程 第4讲 HObject/HImage Mat相互转换(tcy)

网上有很多相互转换程序,但并不知那个正确,本文对相互转换后的结果和原对象比较是否相同判断转换是否正确。经测试ok.本文包括转换代码及测试是否相同。 1.转换程序: /************************************ HObject转为Mat:time:2021/3/16 V1.0 *************************************/ cv::Mat HalconClass::HObjectToMat(const HalconCpp::HObject&..

tcy-阿春 4929

go的iris框架进行接收post请求参数获取与axios(vue)的数据传入

axios的post请求,是如何传formdata给后端的

yasinawolaopo的博客 1305

rk3568 RGMII KSZ8795 MAC TO MAC

参考《Rockchip_Developer_Guide_Linux_MAC_TO_MAC_CN.pdf》

明天乌儿会歌唱 6491

5.13华为OD机试真题 新系统 - 社交网络相同爱好好友查询 (Java/Py/C/C++/Js/Go)

5.13华为OD机试真题 新系统 - 社交网络相同爱好好友查询 (Java/Py/C/C++/Js/Go)

算法大师! 152

iris接口返回json数据封装

生成json格式 { "code": 200, "msg": "", "data": "测试返回第一条json" } 封装json的go文件 package core /** 封装请求返回值 2019年7月17日 结构体中的声明变量首字母必须大写 不然无法被beego解析 */ type ResponseBean struct { Code int `json:"cod...

情怀中的释然~ 4566

1个PID回路如何连接2个执行器(算法和代码)

我们先看下位置型PID的控制框图:2、PID是基于error的控制 所以反馈信号跳动、干扰非常大的话,对PID的闭环控制影响是非常大的,所以对于反馈信号、一定要抗干扰和滤波处理。3、下图是增量型PID的控制框图:4、一个PID输出回路如何连接2个执行器?(有些系统会设置热阀和冷阀才能满足控制要求)。

RXXW_Dor的博客 1810

Iris在log中打印请求信息和返回结果 方便调试

Iris这个框架相关的资料太少,进行任何封装操作都只能点进去看源码进行操作,总结了下打印日志信息的方式,留给有需要的人 大致思路 1、将每次请求返回的数据保存在ctx的values中 2、自定义日志中间件,每次请求done之后调用中间件 3、在日志中间件中打印请求数据 将每次请求返回的数据保存在ctx的values中 import ( "xiaoge/src/core" ) // Test...

情怀中的释然~ 4222

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

golang iris mvc controller出现reflect异常

开发十年,就只剩下这套Java开发体系了 >>>    ...

zhnxin_163的博客 992

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

干货|Golang拦截器的一种实现

点击上方“中兴开发者社区”,关注我们 每天读一篇一线开发者原创好文 前言 说起拦截器,大家一定会想起Java语言。 Java里的拦截器是动态拦截Action调用的对象,它提供了一种机制使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Prog

中兴开发者社区 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Iris微服务框架_golang web框架_完整示例Demo

Iris简介 Iris是一款Go语言中用来开发web应用的框架,该框架支持编写一次并在任何地方以最小的机器功率运行,如Android、ios、Linux和Windows等。该框架只需要一个可执行的服务就可以在平台上运行了。 Iris框架以简单而强大的api而被开发者所熟悉。iris除了为开发者提供非常简单的访问方式外,还同样支持MVC。另外,用iris构建微服务也很容易。 在iris框架的官方网站上,被称为速度最快的Go后端开发框架。在Iris的网站文档上,列出了该框架具备的一些特点和框架特性,列举如下:

yinjl123456的博客 3008

go(iris),token+redis+mysql实现简单登录验证(目录结构和设计思路)

前后半个月左右实现了基本的验证功能,从最初连request数据都不会接收,response不会返回数据,到后来将数据库配置信息分离,将连接l和关闭redis,mysq,函数分离成中间件,并一次又一次重构代码,降低逻辑复杂度,完善程序结构,go让我体验到了服务器代码的优美和严谨。 现在看来go的设计很优秀。从简单的接触larveral比较来看,go的中间件能极大简化接口的验证处理,函数多返回值和错...

qq_26372385的博客 5426

Go Iris学习一HTTP2/路由/视图

package main import ( "github.com/kataras/iris" ) func myAuthMidllewareHandler(context iris.Context) { context.WriteString("Authentication failed") context.Next() } func userProfileHandler(contex...

www.shuaibo.wang|王帅博 1万+

【Go】Go-Iris框架实战之电商秒杀系统②核心优化

文章目录第9章 系统分析&前端优化【核心优化方案落地9-2 秒杀分布式架构设计页面静态化的几种方式9-9 CDN原理和作用第10章 服务端性能优化之实现cookie验证后端优化思路基础架构与优化的的架构对比突破Session限制(Cookie代替)cookie与session的区别第11章 服务端性能优化之分布式验证实现11-1 分布式概念第12章 服务端性能优化解决超卖&引入消息队列第14章 课程总结 第9章 系统分析&前端优化【核心优化方案落地 9-2 秒杀分布式架构设计 页面

王大阳的博客 1123

Go Revel - Interceptors(拦截器)

`interceptor`拦截器是revel框架在执行一个`action`的前后所调用的函数。他允许以AOP方式进行开发,这种模式非常有用: 1、记录请求日志 2、错误处理 3、状态保持 在revel中,可以使用两种形式的拦截器: 1、函数拦截器: 一个满足`InterceptorFunc`接口的函数,它不会访问任何一个特定的`controller`调用;可...

weixin_33958366的博客 270

项目中 http响应拦截器

// 超时时间axios.defaults.timeout = 5000;// http请求拦截器axios.interceptors.request.use(config => {    // MintUI Loading方法    // Indicator.open();    return config;}, error => {    // Indicator.close();...

jiao512的专栏 1446

Golang Iris官方文档

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34233618的博客 1386

mysql 自定义异常_iris的异常处理及返回统一自定义异常

自定义异常结构体package modeltype BusinessException struct {Status int `json:"status"`Code string `json:"code"`Message string `json:"message"`Trace string `json:"trace"`}func (e *BusinessException) E...

weixin_42119866的博客 502

ResponseWriter

*response是ResponseWriter接口的实现。 WriteHeader方法: 设置响应的状态码,返回错误状态码特别有用。WriteHeader方法在执行完毕之后就不允许对首部进行写入了。 func redirect(w http.ResponseWriter, r *http.Request) { w.Header().Set("location", "https:...

磨镜台的博客 4209

response通过writer输出数据

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置response以什么码表向浏览器写 response.setCharacterEncoding("utf-8"); //指定浏览器以什么码表打

每天进步一点点 9233
上一篇: Go 程序的国际化
下一篇: Go连接Apollo配置中心对比是否已经导入过配置信息
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值