玩儿转MVC之大屌牌儿MVC框架(一)

2023-10-07 16:40
文章标签 框架 mvc 牌儿 玩儿 之大

本文主要是介绍玩儿转MVC之大屌牌儿MVC框架(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

这篇文章标题的确够屌,那么接下来阿海就以这个标题为入口,那么,就请诸位看官们且听我如何吹牛!
在阿海开始吹之前呢,也就是三天前吧,在某群看到过一篇博客,那界面,真心爽!而且阿海最近也在抽时间看关于前段的一些资料。虽然在前段上没什么造诣,但是写个HelloWorld什么的还是可以的,最起码我觉得我的审美观还是比较正常的。

你问我为什么扯到前端上了?哦,是这个样子,前面说到我的审美观比较不错,所以当我看到一个博客的清新大气简约时尚的页面时,又想想自己那个傻不溜秋的博客(blog.321aiyi.com),就萌生了一个完全属于自己的博客的想法!

于是就搭建了一个基于Spring的工程,当然数据库用的还是之前我曾经说过的基于Mybatis封装的神速开发框架。但是吧,尽管Spring很轻量级,但是我觉得写个博客程序什么的有点儿大材小用,直接用Servlet吧,又觉得有点儿麻烦。

于是乎,我决定封装一套用于MVC层的一个小框架,指不定以后什么时候突然兴趣来临写个小东西什么的就能派上用场了呢!

效果演示

哦了,上面的部分纯属乱吹,可以直接无视,在介绍这个MVC之前,我喜欢先让大家们看一下他的运行效果图:

先创建一个Controller:

@MVCController("controller")
public class MyController{//创建完毕~待会儿下面演示的Java代码都是写在这里的
}

测试对象响应体

代码:

    /*** 测试对象返回* @return*/@MVCURL("test")@MVCJsonpublic Object test(){Map<String, Object> result = new HashMap<>();result.put("testString", "Hello World!");result.put("testInteger", 110);result.put("testBoolean", true);String[] liStrings = {"哈哈哈", "嘿嘿嘿", "呵呵呵"};result.put("testList", liStrings);return result;}

启动并访问localhost:8080/Blog/controller/test.e
大屌牌儿MVC框架测试对象返回图片

测试JSP模板

JAVA代码

    /*** 测试JSP模板* @param request* @param response* @return*/@MVCURL("test2")public String toJsp(HttpServletRequest request, HttpServletResponse response){request.setAttribute("va", "如果你看到这句话,说明JSP模板成功了!");return "test";}

JSP代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${va }
</body>
</html>

运行效果:
大屌牌儿MVC框架测试JSP模板截图

测试自定义参数接收

JAVA代码:

    /*** 测试自定义参数接收* @param name* @param sex* @return*/@MVCURL("test4")@MVCJsonpublic Map<String, Object> test4(String name, String sex, int age){Map<String, Object> result = new HashMap<>();result.put("姓名", name);result.put("性别", sex);result.put("年龄", age);return result;}

运行效果
测试MVC的自定义参数列表结果截图

测试Model的封装

Java代码:

    /*** 测试Model的封装* @param name* @param model* @return*/@MVCURL("test5")public String test5(String name, Model model){model.set("name", name);return "testJsp";}

JSP代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>你传入的姓名是:${name }
</body>
</html>

结果截图:
测试MVC框架的Model封装截图

到此,演示完毕,毕竟这个框架才写了三天,并且都是业余时间写的,所以也就只有这些比较常用的功能了,好在可以直接用HttpServletRequest和HttpServletResponse来处理所以一般情况下的小程序用这个做MVC感觉已经差不多了。
不是哥们儿我吹啊,想当年,哥们儿我小学的时候就就会黑别人QQ了(手动滑稽)~


简介

接下来我把这个封装的东西暂且叫他MVC框架,或者mvc框架。如果你觉得不够亲切,可以叫他《大屌牌儿MVC框架》
说说它的整体结构吧,他的整体结构其实就是一个单利的基于Hash表的ControllerBean全局管理控制容器和一个RequestMethod全局管理控制容器。(说白了就是俩静态Map)

下面是这个容器类的代码,如果被我之前说的一大堆没用的给整蒙了甚至找不到北的话,你看了下面这个代码或许会想“TMD这么简单的东西说那么复杂干毛!”:

package com.aiyi.mvc.reflection;import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;import com.aiyi.mvc.annotations.RequesMethod;/*** 对象容器* @author 郭胜凯* @time 2016年11月8日 下午2:47:18* @addr blog.321aiyi.com* @email 719348277@qq.com*/
public class BeanContainer {/*** 对象容器集合*/public static Map<String, Object> ObjectContainer = new HashMap<>();/*** 方法容器集合*/public static Map<String, Method> MethodContainer = new HashMap<>();/*** 向容器中添加一个Bean* @param string* @param filterUrl* @param class1*/public static void setBean(String type, String filterUrl, Object bean) {// TODO Auto-generated method stubObjectContainer.put("<t>" + type + "</t><u>" + filterUrl + "</u>", bean);}/*** 向容器中添加一个Url映射* @param requesMethod* @param url* @param method*/public static void setMethod(RequesMethod requesMethod, String url, Method method) {// TODO Auto-generated method stubMethodContainer.put("<m>" + requesMethod.name().toUpperCase() + "</m><u>" + url + "</u>", method);}public static Method getMethod(String method, String uri) {// TODO Auto-generated method stubreturn MethodContainer.get("<m>" + method.toUpperCase() + "</m><u>" + uri + "</u>");}public static Object getBean(String type, String uri) {// TODO Auto-generated method stubreturn ObjectContainer.get("<t>" + type + "</t><u>" + type + "</u>");}}

哈哈,就是这么简单,就是俩Map而已!然后就是定义了一些通过客户端请求URI获取Controller和Method的一些方法。仅此而已!别问我我为什么要卖这么个关子,现在很多程序员都把很简单的东西说的那么复杂,还满嘴的名词儿一个一个的往外蹦,其实说的都是HelloWorld级别的东西,还自我认为很良好的样子。不只是程序员,连一些其他的职位也是这个样子,感觉会几个词儿技术就会变厉害似的。

下面看一个有趣的对话:

甲:你会MQ嘛?
我:消息队列就消息队列呗,还M什么Q呀 ,别问我我不会!
甲:…教教我

其实我当时真不会消息队列,但是我认为这类的问题,我可以花一个小时的时间阅读一下资料就能解决的问题。要知道一个开源的Java,他的东西那么那么多,你没有学完的时候,所以对于Java工程师而言,我觉得做的最多的还是现学现用!活学活用!随用而学!
要知道没有什么问题是看一遍文档解决不了的,如果有,那就看两遍!


好了一不小心又给跑题了,接下来回到正题,说一下这个MVC框架的核心:

另外,他的核心呢,就是一个Servlet!(这点儿和Spring MVC挺像)
当然,他也有属于自己的Filter,而且我已经定义好了Filter注解了,但是我还没有给他加上任何功能。
所以我想到这里大家应该知道怎么配这个框架了吧!

先不说怎么配,把这个核心的Servlet代码给大家亮一下:

package com.aiyi.mvc;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.Set;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import com.aiyi.mvc.annotations.MVCController;
import com.aiyi.mvc.annotations.MVCFilter;
import com.aiyi.mvc.annotations.MVCJson;
import com.aiyi.mvc.annotations.MVCURL;
import com.aiyi.mvc.reflection.BeanContainer;
import com.aiyi.mvc.reflection.BeanUtil;
import com.aiyi.mvc.reflection.Model;
import com.aiyi.mvc.util.PropertiesUtil;
import com.aiyi.mvc.util.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;/*** MVC核心控制器* @author 郭胜凯* @time 2016年11月9日 上午11:23:38* @addr blog.321aiyi.com* @email 719348277@qq.com*/
public class CoreServlet extends HttpServlet{/*** */private static final long serialVersionUID = 5441344237169464974L;private boolean isChinaseUincode = false;private String contentCharset = "utf-8";private Set<Class<?>> classes;private String templateFrist = null;private String templateSuffix = ".jsp";private String contentPath = "";@Overridepublic void init() throws ServletException {// TODO Auto-generated method stubProperties properites = new PropertiesUtil().getProperites("mvc/config.properties");/*** 中文Unicode编码*/isChinaseUincode = properites.getProperty("ChinaseUnicode", "false").equalsIgnoreCase("true");/*** 字符集*/contentCharset = properites.getProperty("ContentCharset", "UTF-8");/*** JSP模板前缀*/templateFrist = properites.getProperty("TemplateFrist", "/");/*** JSP模板后缀*/templateSuffix = properites.getProperty("TemplateSuffix", ".jsp");classes = BeanUtil.getClasses(properites.getProperty("ClassPacketName"));for (Class<?> c : classes) {//实例化过滤器MVCFilter filterAnm = c.getAnnotation(MVCFilter.class);if (null != filterAnm) {try {String value = filterAnm.value();if (null == value || "".equals(value)) {value = "/*";}Object bean = c.newInstance();BeanContainer.setBean("filter", value, bean);} catch (InstantiationException | IllegalAccessException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}super.init();}@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, IllegalArgumentException {// TODO Auto-generated method stub//获取客户端请求路径和请求MethodcontentPath = request.getContextPath() + "/";String requestURI = request.getRequestURI().replace(contentPath, "");String requestMehod = request.getMethod();//根据请求路径,从Bean容器中获取对应处理方法Method method = BeanContainer.getMethod(requestMehod, requestURI);if (null == method) {//容器中没有对应方法的实例,扫描注解并加载实例到容器中for (Class<?> c : classes) {MVCController controllerAnm = c.getAnnotation(MVCController.class);if (null != controllerAnm) {String controllerUri = controllerAnm.value();if (requestURI.indexOf(controllerUri) != -1) {Method[] methods = c.getMethods();for (Method meth : methods) {MVCURL urlAnm = meth.getAnnotation(MVCURL.class);if (null != urlAnm) {String reqUri = urlAnm.value();if (controllerUri.charAt(0) == '/') {controllerUri = controllerUri.substring(1);}//整理完整请求URIif (controllerUri.charAt(controllerUri.length() - 1) == '/') {if (reqUri.charAt(0) == '/') {reqUri = controllerUri + reqUri.substring(1);}else{reqUri = controllerUri + reqUri;}}else{if (requestURI.charAt(0) == '/') {reqUri = controllerUri + reqUri;}else{reqUri = controllerUri + "/" + reqUri;}}if (requestURI.charAt(requestURI.length() - 1) != '/' && requestURI.indexOf(".") != -1) {requestURI = requestURI.substring(0, requestURI.lastIndexOf("."));}if (requestURI.equals(reqUri) && requestMehod.equalsIgnoreCase(urlAnm.method().name())) {//找到对应方法,实例化到Bean容器中BeanContainer.setMethod(urlAnm.method(), reqUri, meth);Log.info("实例化方法 -" + urlAnm.method() + ":" + reqUri + "[" + meth + "]");//如果该方法的类没有被实例化则实例化类到Bean容器中Object bean = BeanContainer.getBean("controller", controllerUri);if (null == bean) {try {bean = c.newInstance();BeanContainer.setBean("controller", controllerUri, bean);Log.info("实例化控制器 " + ":" + controllerUri + "[" + c.getName() + "]");} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}try {goToMethod(request, response, meth, bean);return;} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}}}}else{for (Class<?> c : classes) {MVCController controllerAnm = c.getAnnotation(MVCController.class);if (null != controllerAnm) {String controllerUri = controllerAnm.value();Object bean = BeanContainer.getBean("controller", controllerUri);if (null == bean) {try {bean = c.newInstance();BeanContainer.setBean("controller", controllerUri, bean);Log.info("实例化控制器 " + ":" + controllerUri + "[" + c.getName() + "]");} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}try {goToMethod(request, response, method, bean);return;} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}response.sendError(404);
//      super.service(request, response);}/*** 反射执行控制器的URL处理方法* @param request* @param response* @param method* @param controller* @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws IOException * @throws ServletException */private void goToMethod(HttpServletRequest request, HttpServletResponse response, Method method, Object controller) throws IllegalArgumentException, InvocationTargetException, IOException, ServletException, IllegalAccessException{response.setCharacterEncoding(contentCharset);Class<?>[] parameterTypes = method.getParameterTypes();//当该方法的参数列表是空的时候,直接调用if (parameterTypes.length == 0) {Object result = method.invoke(controller);if (null != result) {MVCJson jsonAnm = method.getAnnotation(MVCJson.class);//标有Json注解并具有返回值的方法将返回值序列成Json并输出if (null != jsonAnm) {response.setContentType("Content-Type: application/json;charset" + contentCharset);String jsonResult = null;if (isChinaseUincode) {jsonResult = StringUtil.chinaToUnicode(new ObjectMapper().writeValueAsString(result));}else{jsonResult = new ObjectMapper().writeValueAsString(result);}response.getWriter().print(jsonResult);return;}else if (result instanceof String) {//否则返回String文本,该文本对应一个Jsp模板路径String templatePath = String.valueOf(result);if (templatePath.charAt(0) == '/') {if (!templateFrist.equals("/")) {if (templateFrist.charAt(templateFrist.length() - 1) == '/') {templatePath = templateFrist + templatePath.substring(1);}else{templatePath = templateFrist + templatePath;}}}else{if (templateFrist.charAt(templateFrist.length() - 1) == '/') {templatePath = templateFrist + templatePath;}else{templatePath = templateFrist + "/" + templatePath;}}templatePath += templateSuffix;if (templatePath.charAt(0) != '/') {templatePath = "/" + templatePath;}request.getRequestDispatcher(templatePath).forward(request, response);return;}else{//以上两种都不是,直接404response.sendError(404);return;}}}else{//Controller中带有参数Object[] params = new Object[parameterTypes.length];String[] methodParamNames = MethodUtil.getMethodParameterNamesByAsm4(controller.getClass(), method);Map<String, String[]> parameterMap = request.getParameterMap();for (int i = 0; i < parameterTypes.length; i++) {if (parameterTypes[i].equals(HttpServletRequest.class)) {params[i] = request;methodParamNames[i] = null;continue;}if (parameterTypes[i].equals(HttpServletResponse.class)) {params[i] = response;methodParamNames[i] = null;continue;}if (parameterTypes[i].equals(HttpSession.class)) {params[i] = request.getSession();methodParamNames[i] = null;continue;}if (parameterTypes[i].equals(Model.class)) {params[i] = new Model(request);methodParamNames[i] = null;continue;}//除了标准的一些Http处理参数外,还有一些额外的参数,有戏了,匹配用户请求参数名if (null != methodParamNames[i]) {String[] strings = parameterMap.get(methodParamNames[i]);if (null != strings) {if (strings.length == 1) {if (parameterTypes[i].equals(Integer.class) || parameterTypes[i].equals(Integer.TYPE)) {try {params[i] = Integer.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}if (parameterTypes[i].equals(Long.class) || parameterTypes[i].equals(Long.TYPE)) {try {params[i] = Long.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}if (parameterTypes[i].equals(Double.class) || parameterTypes[i].equals(Double.TYPE)) {try {params[i] = Double.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}if (parameterTypes[i].equals(Float.class) || parameterTypes[i].equals(Float.TYPE)) {try {params[i] = Float.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}if (parameterTypes[i].equals(Short.class) || parameterTypes[i].equals(Short.TYPE)) {try {params[i] = Short.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}if (parameterTypes[i].equals(Boolean.class) || parameterTypes[i].equals(Boolean.TYPE)) {try {params[i] = Boolean.valueOf(strings[0]);} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("客户端提交数据类型与服务端接收类型不相符(参数:" + methodParamNames[i] + ")");}continue;}//上面的都没戏了,直接贴数据params[i] = strings[0];continue;}//有数组!例如复选框之类的表单!//!!!待完善else{}}}}try {Object result = method.invoke(controller, params);if (null != result) {MVCJson jsonAnm = method.getAnnotation(MVCJson.class);//标有Json注解并具有返回值的方法将返回值序列成Json并输出if (null != jsonAnm) {response.setContentType("Content-Type: application/json;charset" + contentCharset);String jsonResult = null;if (isChinaseUincode) {jsonResult = StringUtil.chinaToUnicode(new ObjectMapper().writeValueAsString(result));}else{jsonResult = new ObjectMapper().writeValueAsString(result);}response.getWriter().print(jsonResult);return;}else if (result instanceof String) {//否则返回String文本,该文本对应一个Jsp模板路径String templatePath = String.valueOf(result);if (templatePath.charAt(0) == '/') {if (!templateFrist.equals("/")) {if (templateFrist.charAt(templateFrist.length() - 1) == '/') {templatePath = templateFrist + templatePath.substring(1);}else{templatePath = templateFrist + templatePath;}}}else{if (templateFrist.charAt(templateFrist.length() - 1) == '/') {templatePath = templateFrist + templatePath;}else{templatePath = templateFrist + "/" + templatePath;}}templatePath += templateSuffix;if (templatePath.charAt(0) != '/') {templatePath = "/" + templatePath;}request.getRequestDispatcher(templatePath).forward(request, response);return;}else{//以上两种都不是,直接404response.sendError(404);return;}}} catch (Exception e) {// TODO: handle exceptionthrow new IllegalArgumentException("请求参数与服务器接收参数不匹配");}}}
}

写道这里,时间又不早了,那么就先到这儿,我就不吊大家胃口了,如果对这个MVC感兴趣,的话我分享到GItHub了,有感兴趣的朋友可以直接在这里down到源码:https://git.coding.net/shengkai/MVC.git

如果有兴趣的朋友可以期待我的下一篇博客《玩儿转MVC之大屌牌儿MVC框架(二)》

这篇关于玩儿转MVC之大屌牌儿MVC框架(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/159068

相关文章

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

Spring MVC 图片上传

引入需要的包 <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简