>  기사  >  백엔드 개발  >  Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)

PHPz
PHPz원래의
2017-04-04 15:32:553142검색

소개

Api비즈니스 로직 제공자로서 프로젝트의 핵심 로직을 전달하므로 상대적으로 로직 복잡도가 높습니다. 이러한 전제하에 코드 작성을 단순화하는 방법, 작성 스타일과 논리 사양을 표준화하고 통일하는 방법, 코드의 유지 관리성과 확장성을 향상시키는 방법을 설명합니다. 응집력은 높고 결합도는 낮은 프로젝트를 구축하는 것이 중요해졌습니다.
예제는 기업 수준의 프로젝트입니다. 프레임워크는 아래와 같습니다

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)

api layer.jpg

보안: Http 요청(DelegatingHan 재정의dler)이 다시 작성되고 요청 측면에서 적법성이 판단되며 서명 요구 사항이 사전 처리됩니다.
클라이언트: 호출 측에서 사용하는 통합 인터페이스 호출 방법을 정의하여 인터페이스 사용을 단순화하고 통합합니다.
Ctrl 레이어: 서비스를 직접 제공하는 역할로 서버에서 RestFul 스타일과 유사한 인터페이스를 직접 제공합니다(완전한 도메인 모델드라이버 , 실제 상황은 항상 불만족스럽고 도메인 추상화 기능이 충분하지 않음) 요청 데이터를 얻고 필요에 따라 FilterFilter를 호출하고 추가 판단을 한 다음
Model. 레이어: 비즈니스 모델 레이어로서 비즈니스 로직의 실제 작동을 제공합니다. 통합 엔터티 모델을 사용하고 데이터 작업을 위해 Ibatis에 연결합니다. 구체적인 코드 구조는 다음과 같습니다.

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)
Api-UML.jpg

자세한 코드 소개는 다음과 같습니다. 각 모듈 및 코드 예시:

엔티티 라이브러리 프로젝트 코드 예시

프로젝트 구조는

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)
entity입니다. jpg

Do

main

모듈을 엔터티 모델로 간단한 코드는 다음과 같습니다. 요청 구조 모델인

public class User
{
      public int Id { get; set; }
      public string NickName { get; set; }
      public string Avatar { get; set; }
}
Request는 일반 인터페이스를 사용하여 연결합니다. 요청 클래스와 제어 반전 역할을 수행하는 반환 클래스입니다.

public abstract class AbstractRequest
{
    public bool ValidateParameters()
    {
        //公用方法示例,验证参数合法性
    }
}
   public interface IRequest<T> where T:AbstractResponse
    {
        //获取接口名称
        string GetApiName();

        //获取接口编码
        string GetApiCode();
    }
//获取User信息的请求结构定义
  public class GetUserRequest:AbstractRequest,IRequest<GetUserResponse>
    {
        public int Id { get; set; }

        public string GetApiName()
        {
            return "User.GetUserDetail";
        }

        public string GetApiCode()
        {
            return "User001";
        }
    }

응답 모듈은 요청의 반환 유형으로 소비자가 일관성 반환 코드를 판단하고 처리할 수 있도록 통합된 반환 구조를 정의합니다.

public abstract class AbstractResponse
    {
        //返回码
        public int Code { get; set; }
        //报错信息
        public string Message { get; set; }
    }
 public class GetUserResponse:AbstractResponse
    {
        public User User { get; set; }
    }

서비스 프로젝트 코드 예시

프로젝트 구조는

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)
service.jpg

코드 예:

 public interface IUserService
    {
        GetUserResponse GetUser(int id);
    }
 public class BaseService
    {
        //protected SqlInstance sqlInstance;
        public BaseService()
        {
            //sqlInstance=new SqlInstance(); //实例化数据库连接
            //...
        }
        //...
    }
  public class UserService:BaseService,IUserService
    {
        public GetUserResponse GetUser(int id)
        {
            //链接数据库获取数据
            //...
            throw new NotImplementedException();
        }
    }

보안

클래스 라이브러리
코드 예클래스 라이브러리는
보안

문제만 처리하고 API 요청 항목에 권한 판단을 추가합니다. Http 요청을 다시 작성하는 방법을 사용하십시오. 코드 예시

public class MyHandler : DelegatingHandler
    {
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            IEnumerable<string> keyEnumerable;
            var t1 = request.Headers.TryGetValues("key", out keyEnumerable);
            var key = keyEnumerable.FirstOrDefault();
            if (!true)//验证类似于token的权限
            {
                return await Task.Factory.StartNew<HttpResponseMessage>(
                            () => new HttpResponseMessage(HttpStatusCode.Forbidden)
                            {
                                Content = new StringContent("error message")
                            });
            }
            //如果有signature,判断,并加结果标志,没有的话,清除signature相关信息,防止伪造。
            //.....
            return await base.SendAsync(request, cancellationToken);
        }
    }

추상화된 권한 판단은 webapi 엔드에 직접 호출하여 라우팅

구성 코드에 추가할 수 있습니다. WebApi 프로젝트 예시

webapi는 인터페이스의 실제 정의로서 인터페이스 파일의 실제 규칙을 정의하고 이에 상응하는 인터페이스의
보안 관리

및 권한 제어를 수행합니다. . WeChat의 권한 제어를 알아보기 위해 여러 인터페이스가 대략적으로 결정되었습니다.

Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)
InterfacePermissions.png

이에 대한 판단 권한은 모두 중앙 집중식 관리가 보안에서 수행됩니다. 인터페이스 정의는 해당 로직의 합법성을 판단하는 데에만 사용되어야 합니다.

코드 예:

public class UserController : ApiController
    {
        private IUserService userService;

        public UserController()
        {
            userService=new UserService();
        }

        [Signature]//安全签名过滤器判断
        [HttpPost]
        public GetUserResponse GetUser(GetUserRequest request)
        {
            //参数判断,安全性判断等等
            var ret = userService.GetUser(request.Id);
            return ret;
        }

    }

위는 사용자 정보를 얻기 위한 인터페이스 예시입니다. 인터페이스 입구의 라우팅 구성으로 요청의 적법성을 판단해야 하는 라우팅 구성 코드는 다음과 같습니다. :
public static void Register(HttpConfiguration config)
{
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}",
                defaults: new { id = RouteParameter.Optional }
            );
            //添加的代码,添加http请求的入口处理
            config.MessageHandlers.Add(new MyHandler());
}

클라이언트 클래스 라이브러리 코드 예

클라이언트 클래스 라이브러리는 인터페이스에서 호출되는 공용 메서드를 정의합니다.
1. 일반 인터페이스를 사용하여 요청 클래스와 반환 클래스를 캡슐화하여 호출 코드 작성을 단순화합니다.

2. 또한 소비자는 도메인 간 문제를 방지하면서 프록시 클래스를 통해 인터페이스를 호출할 수 있습니다.
3. 소비자 호출은 모두 통일된 클래스 라이브러리를 사용하는 데 동의하므로 로그 처리가 통일되고 반환되는 오류도 일관되게 정의할 수 있습니다.
코드 예시는 다음과 같습니다.

 public interface IClient
 {
     T Execute<T>(IRequest<T> request) where T : AbstractResponse;
 }

public class DefaultClient:IClient
    {
        private readonly string appKey;
        private readonly string appSecret;
        private readonly string baseUrl = "http://localhost:16469/api/";
        private readonly bool isNeedLogFile = false;
        private readonly LogFile logFile;
        public static readonly string SecureHeaderAppKey = "secure_head_appkey";
        public static readonly string SecureHeaderSignature = "secure_head_signature";

        public DefaultClient()
        {
            baseUrl = ConfigurationManager.AppSettings["service_base_url"];
            appKey = ConfigurationManager.AppSettings["app_key"];
            appSecret = ConfigurationManager.AppSettings["app_secret"];
            isNeedLogFile = "1".Equals(ConfigurationManager.AppSettings["client_log_file"]);
            logFile = new LogFile("client_log_path");
            logFile.SubPath = appKey;
        }

        public DefaultClient(string serviceBase, string code, string key)
        {
            baseUrl = serviceBase;
            appKey = code;
            appSecret = key;
        }
        public T Execute<T>(IRequest<T> request) where T : AbstractResponse
        {
            var webRequest = (HttpWebRequest)WebRequest.Create(baseUrl + request.GetApiName());
            webRequest.Method = "POST";

            string reqJson;
            string sign;
            using (Stream rs = webRequest.GetRequestStream())
            {
                reqJson = JsonConvert.SerializeObject(request);

                byte[] reqBytes = Encoding.UTF8.GetBytes(reqJson);
                rs.Write(reqBytes, 0, reqBytes.Length);
                rs.Close();
            }

            webRequest.ContentType = "application/json";
            webRequest.Headers.Add(SecureHeaderAppKey, appKey);
            sign = ComputeHash(appKey, appSecret, reqJson);
            webRequest.Headers.Add(SecureHeaderSignature, sign);

            //记录日志
            if (isNeedLogFile)
            {
                logFile.Log(string.Format("[{0}] 请求内容: {1}", request.GetApiCode(), reqJson));
                logFile.Log(string.Format("[{0}] 请求签名: {1}", request.GetApiCode(), sign));
            }

            try
            {
                using (var resp = (HttpWebResponse)webRequest.GetResponse())
                {
                    try
                    {
                        Stream respStream = resp.GetResponseStream();

                        if (respStream == null)
                        {
                            throw new WebException("GetResponseStream returned null");
                        }
                        var streamReader = new StreamReader(respStream);
                        string respStr = streamReader.ReadToEnd();
                        //记录日志
                        if (isNeedLogFile)
                        {
                            logFile.Log(string.Format("[{0}] 响应内容: {1}", request.GetApiCode(), respStr));
                        }
                        return JsonConvert.DeserializeObject<T>(respStr);
                    }
                    catch (Exception e)
                    {
                        //记录日志
                        if (isNeedLogFile)
                        {
                            logFile.Log(string.Format("[{0}] 响应错误: {1}", request.GetApiCode(), e.Message));
                        }
                        throw new ApplicationException(e.Message, e);
                    }
                }
            }
            catch (WebException e)
            {
                var errMsg = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
                //记录日志
                if (isNeedLogFile)
                {
                    logFile.Log(string.Format("[{0}] 请求错误: {1}", request.GetApiCode(), errMsg));
                }
                throw new APIServiceException(errMsg);
            }
        }
        private string ComputeHash(string key, string secret, string body)
        {
            return
                Convert.ToBase64String(
                    SHA1.Create().ComputeHash(Encoding.Default.GetBytes(string.Concat(key, secret, body.Trim()))));
        }
    }

以上就是Api项目端的各个核心环节的详细介绍。
接下来会对调用端即前端进行简单的介绍。Asp.net(三)Web端展示

위 내용은 Asp.net (2) 비즈니스 처리 인터페이스 프로젝트(Web Api)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.