`
AngelAndAngel
  • 浏览: 237299 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

动手开发自己的mvc-1----实现初步的控制层,实现各种配置和资源获取

阅读更多
     mvc框架最基础的功能就是跳转,struts2支持注解+xml配置跳转,我个人认为用注解来配置跳转不是一个好的做法,看似比较简单,但是action多了之后查找起来比较不方便,而且把配置信息放在类里面实际上跟解耦理念是相悖的(不过每个人有自己喜好),所以在这里我打算把跳转层设计成xml配置的,其他层设计成注解的。
      配置跳转需要用到的知识有:反射,xml读取。反射是实现动态装配的基础,它使我们的程序更具动态性,可扩展性,几乎所有流行的框架都以它为基础实现。xml读取基本都会采用dom4j完成。
      mvc实现跳转的过程:xml配置命名空间,Action处理类,请求的action方法和跳转的页面,在form提交请求后,被中心Servlet处理,解析出请求的路径,根据xml配置的各种信息,反射调用目标Action类的处理方法,并且根据xml配置的目标跳转页面进行跳转。
      所以,我们提炼出的 核心配置有
      1,namcespace:命名空间,不同模块有不同的namespace,
      2,name:form请求的名字。
      3,method:name对应的Action处理方法名,会被反射调用
      4, class:Action处理类的全路径,用于在中心Servlet反射生成.
     5, result子标签:Action处理后的跳转页面,跳转方式为forward或redirect

      我们新建一个web工程(Eclipse),取名MVC。
       接着新建一个Servlet,取名MainServlet,做中心处理器用。
       src目录下新建control.xml当作跳转配置文件,control.xml如下
      
<? xml version ="1.0" encoding= "UTF-8" ?>
< actions>
    <global-results>
          <result name="userindex" type="redirect">test/test1.action</result>
       </global-results>   
    <namespace name= "/test" >
           <action name= "test1" method= "test1"
               class= "com.test.action.TestAction" >
               <result name= "success" type= "forward" >success.jsp </result >
               <result name= "error" type= "redirect" >error.jsp </result >
           </ action>

           <action name= "test2" method= "test2"
               class= "com.test.action.TestAction" >
               <result name= "success" type= "forward" >success.jsp </result >
               <result name= "error" type= "forward" >error.jsp </result >
           </ action>

           <action name= "test3" method= "test3"
               class= "com.test.action.TestAction" >
               <result name= "success" type= "forward" >success.jsp </result >
               <result name= "error" type= "forward" >error.jsp </result >
           </ action>
      </namespace >
     
</ actions>


     配置web.xml,使其拦截所有action结尾的请求,我的配置如下:

<servlet>
     <servlet-name >mainservlet </servlet-name>
     <servlet-class >org.love.servlet.MainServlet </servlet-class>
     
     
     <init-param >
     <description >control action的配置文件路径 不配置,则默认为src根路径的control.xml文件 
       </description>
     <param-name >CONTROL_CONFIG </param-name>
     <param-value >classpath:control.xml </param-value>
     </init-param >
     
     <init-param >
     <description >字符编码 </description>
     <param-name >ENCODING </param-name>
     <param-value >UTF-8 </param-value>
     </init-param >
     
     </servlet >
     
     <servlet-mapping >
     <servlet-name >mainservlet </servlet-name>
     <url-pattern >*.action</url-pattern>
     </servlet-mapping >


之所以把CONTROL_CONFIG 配制成
classpath:control.xml是因为更好的读取不同路径下的文件。

这样,所有.action的请求都会进入MainServlet这个中心处理器,并且把配置文件一并传入,在servlet初始化(init()方法会在第一次请求时调用
)阶段读取配置文件信息,并缓存起来。
一般来说,资源管理类都可以设计成单例,即满足应用需要,又节省内存,并且代码看起来更加清晰,所以我这里新建ControlXml类,用来专门读取control.xml文件
在实现此类之前,还需要把配置文件各元素对应成不同javabean,类对应如下


Namespace持有ActionVo列表,ActionVo持有Result列表,ControlXml持有Namespace的map结构就行了。
ControlXML代码如下:
package org.love.servlet.util;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.love.converter.DateConverter;
import org.love.converter.FileConverter;
import org.love.converter.IntegerConverter;
import org.love.converter.TypeConverter;

/**
 * 用来解析控制器的xml文件
 *
 * @author Administrator
 *
 */
public class ControlXML {

     public final static String CONTROL_CONFIG = "control.xml";

     private static ControlXML controlXml = new ControlXML();

     private Map<String, Namespace> namespaces = new HashMap<String, Namespace>();

     private Map<String,TypeConverter> convertMap= new HashMap<String, TypeConverter>();
     
     private Map<String,Result> globalResults= new HashMap<String, Result>();
     
     public Map<String, Result> getGlobalResults() {
           return globalResults;
     }

     private ControlXML() {
           /*convertMap.put("java.util.Date", new DateConverter());
          convertMap.put("java.lang.Integer", new IntegerConverter());
          convertMap.put("org.love.po.FilePo", new FileConverter());*/
     }

     public static ControlXML getInstance() {
           return controlXml;
     }

     public void readXml(String xmlurl) throws DocumentException, InstantiationException, IllegalAccessException, ClassNotFoundException {
           /* 读取xml文件 */
          SAXReader reader = new SAXReader();
          Document document = reader.read( new File(xmlurl));
          Element rootElement = document.getRootElement();

           /* 读取namespace配置(包含result配置) start */
           List<Element> namespaces_list = rootElement.elements("namespace" );
           for (Element namespace : namespaces_list) {
               /* 读取action后的集合 */
              Map<String, ActionVo> actions = new HashMap<String, ActionVo>();

               /* 读取action配置(包含result配置) start */
               List actions_list = namespace.elements("action" );
               for (Iterator it = actions_list.iterator(); it.hasNext();) {
                   Element action = (Element) it.next();
                   ActionVo avo = new ActionVo();
                   avo.setName(action.attributeValue( "name"));
                   avo.setMethod(action.attributeValue( "method"));
                   avo.setClassName(action.attributeValue( "class"));

                    List<Element> avo_results = action.elements("result" );
                   Map<String,Result> list_result = new HashMap<String, Result>();
                    for (Element result : avo_results) {
                        Result rs = new Result();
                        rs.setName(result.attributeValue( "name"));
                        rs.setType(result.attributeValue( "type"));
                        rs.setUrltext(result.getText().trim());
                        list_result.put(rs.getName(),rs);
                   }
                   avo.setResults(list_result);
                   actions.put(avo.getName(), avo);
              }
               /* 读取action配置(包含result配置) end */

                namespaces.put(namespace.attributeValue( "name"), new Namespace(
                        namespace.attributeValue( "name"), actions));
          }
           /* 读取namespace配置(包含result配置) end */

           /*读取converter配置 start*/
           /*List<Element> converter_list = rootElement.elements("converter");
          for(Element convertElement:converter_list){
              String type=convertElement.attributeValue("type");
              String handle=convertElement.attributeValue("handle");
              TypeConverter tc=(TypeConverter)(Class.forName(handle).newInstance());
              convertMap.put(type,tc);
          }*/
           /*读取converter配置 end*/
          
           /* 读取 global-results start*/
           List <Element> global_results_list = rootElement.elements("global-results");
          if(global_results_list!=null && global_results_list.size()>0){
              Element global_results=global_results_list.get(0);
               List<Element> results=global_results.elements("result");
              for(Element result:results){
                   Result rs = new Result();
                   rs.setName(result.attributeValue("name"));
                   rs.setType(result.attributeValue("type"));
                   rs.setUrltext(result.getText().trim());
                   globalResults.put(rs.getName(),rs);
              }    
          }
          
          
           /* 读取 global-results end*/
          
           /* 后续会加上其他配置 */

     }

     public ActionVo getAction(String namespacename, String actionname) {
           if ( namespaces == null || namespaces.isEmpty()) {
               throw new RuntimeException( "请确保之前调用了readXml(xml)方法" );
          }
          Namespace ns = namespaces.get(namespacename);
          ActionVo avo = null;
           if (ns != null) {
              avo=ns.getListActions().get(actionname);
          }
          
           return avo;
     }

   

     public Map<String, TypeConverter> getConvertMap() {
           return convertMap;
     }

}


代码中注释的部分以后会有详细讲解,事实是只要代码结构清晰,增删功能都比较容易。
下面就可以在MainServlet的方法中进行读取了,核心代码如下:
ControlXML controlXml = ControlXML.getInstance();
          String control_config = sc.getInitParameter("CONTROL_CONFIG" );

           if (control_config == null || control_config.trim().equals("" )) {
              control_config = Thread.currentThread().getContextClassLoader()
                        .getResource(ControlXML. CONTROL_CONFIG).getFile();
          } else if (control_config.startsWith("classpath:" )) {
              control_config = control_config.split(":" )[1];
              control_config = Thread.currentThread().getContextClassLoader()
                        .getResource(control_config).getFile();
          } else {
              control_config = sc.getServletContext().getRealPath("WEB-INF" )
                        +File. separator+ control_config;
          }
       try {
              controlXml.readXml(control_config);
          } catch (Exception e) {
              e.printStackTrace();
          }


control.xml不一定放在src下,也有可能是web-inf下,所以这里需要多做几次判断,保证在常用目录下可以找到文件,这里默认为src下。
上面是所有解析工作,下一步:编写MainServlet,使其处理各种请求。

解析请求的核心工作分这几步:
1,从requestUri解析namespace,action
2,在配置资源类ControlXml中获得此Namcespace下的action信息,生成Action实例。
3,执行对应的Action方法,根据返回值得到此Action配置的result,跳转到页面。

实现如下:
String requestURI = request.getRequestURI();
//假如以"/"结尾,则截取url,方便后面解析
if (requestURI.endsWith("/" )) {
   requestURI = requestURI.substring(0, requestURI.length() - 1);
}
String namespace = requestURI.substring(0, requestURI.lastIndexOf("/" ));
String actionname = requestURI.substring(
                   requestURI.lastIndexOf( "/") + 1, requestURI.lastIndexOf("." ));

得到相应Action
ControlXML controlXml = ControlXML.getInstance();
ActionVo avo = controlXml.getAction(namespace, actionname);
Object action = InvocakeHelp.newInstance(avo.getClassName(), null);

反射调用Action的方法,并返回字符串
Object  actionValue=InvocakeHelp.invokeMethod(action,avo.getMethod(),null);

首先根据globalResult配置判断是否有此Result,不存在则从各个action的result里获取
Result result = controlXml.getGlobalResults().get(actionValue);
if(result== null){
   result = avo.getResults().get(actionValue);
}
              

//跳转到配置的页面
          if ("redirect" .equals(result.getType())) {
               response.sendRedirect(request.getContextPath() + "/"
                        + result.getUrltext());
          } else {
              request.getRequestDispatcher( "/" + result.getUrltext()).forward(
                        request, response);
          }  

InvocakeHelp这个是反射工具类,实现起来不复杂,核心代码如下



     public static Object newInstance(String className, Object[] args) {
           try {
              Class newClass = Class. forName(className);
               if (args == null || args. length == 0) {
                    return newClass.newInstance();
              } else {
                   Class[] argsClasses = new Class[args.length];
                    for ( int i = 0; i < args. length; i++) {
                        argsClasses[i] = args[i].getClass();
                   }
                   Constructor cons = newClass.getConstructor(argsClasses);
                    return cons.newInstance(args);
              }

          } catch (ClassNotFoundException e) {
              e.printStackTrace();
          } catch (Exception ex) {
              ex.printStackTrace();
          }
           return null;
     }

     public static Object invokeMethod(Object owner, String methodName,
              Object[] args) {
          Class ownerClass = owner.getClass();
          Class[] argsClass = null;
           if (args != null && args. length != 0) {
              argsClass = new Class[args. length];
               for ( int i = 0; i < args. length; i++) {
                   argsClass[i] = args[i].getClass();
              }
          }
           try {
              Method method = ownerClass.getMethod(methodName, argsClass);
               return method.invoke(owner, args);
          } catch (SecurityException e) {
              e.printStackTrace();
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          } catch (Exception ex) {
              ex.printStackTrace();
          }

           return null;
     }
     
     /**
      * 调用对象的set方法
      *
      * @param obj
      * @param fieldName
      * @param value
      * @param fieldType
      */
     public static void callSetMethod(Object owner, String fieldName,
              Object value) {
          String setName = "set" + fieldName.substring(0, 1).toUpperCase()
                   + fieldName.substring(1);
          Class ownerClass = owner.getClass();
           try {
              Field field=ownerClass.getField(fieldName);
              Method method = ownerClass.getMethod(setName,field.getType());
              method.invoke(owner,value);
          } catch (Exception e) {
              e.printStackTrace();
          }
          
          
     }
     


看起来大致功能都有了,是不是可以测试下,但是?。。。貌似自己的Action里面没有任何request,response的资源?
现在有两种方式可以得到:
  1,实现接口(或继承)
  2,API得到
有人说第二种方式肯定好点,因为很解耦哦,我觉得不一定,因为我们做任何框架的目标不是为了解耦,只要用着顺手就行,固执的考虑低耦合是效率低下的原因之一,当然,作为一个有理想 有思想的框架,这两种方式都得提供。
其实struts2也遇到过类似问题,解决方式之一是实现资源接口,比如
ServletRequestAwarehue接口,实现它可以获得request,另外还有他的兄弟如ServletResponseAware,SessionAware,ServletContextAware,实现他们可以分别得到response,session,servletContext。
首先我们创建
ContextAction接口,代码如下:
/**
 * 为action提供应用程序,请求,会话等相关的资源
 * @author duyf
 *
 */
public interface ContextAction {
     public void setRequest(HttpServletRequest request);
     public void setResponse(HttpServletResponse response);
     public void setSession(HttpSession session);
     public void setServletContext(ServletContext context); 
}


调出MainServlet,在得到action对象后加入设置代码
if (!(action instanceof ContextAction)) {
               throw new RuntimeException( "当前版本需要实现ContextAction接口" );
          }
          ContextAction ca = (ContextAction) action;
          ca.setRequest(request);
          ca.setResponse(response);
          ca.setSession(request.getSession());
          ca.setServletContext( servletContext);


调出测试Action,声明HttpServletRequest等各种资源对象,实现接口并接收资源,核心代码如下:
protected HttpServletRequest request ;
     protected HttpServletResponse response ;
     protected HttpSession session;
     protected ServletContext servletContext;

     public void setRequest(HttpServletRequest request) {
           this. request = request;
     }

     public void setResponse(HttpServletResponse response) {
           this. response = response;
     }

     public void setServletContext(ServletContext context) {
           this. servletContext = context;
     }

     public void setSession(HttpSession session) {
           this. session = session;
     }


。有木有发觉以后每个action都有这些与业务没什么关系的代码,所以一般做法是,做一个BaseAction类实现ContextAction接口,然后让你的Action继承BaseAction,干掉了冗余代码。这也是java模式中常用的缺省模式。

在实现API获取web资源之前,我们仔细想一下tomcat是怎样响应请求的。
请求tomcat时,tomcat从线程池分配一个空闲线程给此请求,经过数据的包装,会在第一次执行MainServlet的时候,执行init方法(执行一次),并且以后所有请求都会执行同一个MainServlet对象,这样就容易造成Servlet的线程安全问题,(HttpServletRequest线程安全的),所以为了在任何地方都能正确的得到请求资源,我们采用ThreadLocal来存储,ThreadLocal本质上是一个 当前线程和值的键值对,所以保证了在当前任何时候访问此对象都能排除多线程变量的干扰,另外在一般情景下会用static修饰ThreadLocal。
实现方式比较简单:
public class ActionContext {

     public final static String HTTPREQUEST = "httprequest";
     public final static String HTTPRESPONSE = "httpresponse";
     private static ThreadLocal<ActionContext> threadLocal = new ThreadLocal<ActionContext>();

     public static ActionContext getContext() {
           return (ActionContext) threadLocal.get();
     }

     public static void setContext(ActionContext context) {
           threadLocal.set(context);
     }

     public static HttpServletRequest getRequest() {
           return (HttpServletRequest) getContext().get(HTTPREQUEST);
     }

     public static HttpServletResponse getResponse() {
           return (HttpServletResponse) getContext().get(HTTPRESPONSE);
     }

     
     
     public ActionContext() {

     }

     public ActionContext(Map<String, Object> context) {
           this. context = context;
     }

     /* 对象属性 start */
     private Map<String, Object> context = new HashMap<String, Object>();

     /* 对象属性 end */

     /* 对象方法 start */
     public Object get(String key) {
           return context.get(key);
     }

     public Object put(String key, Object value) {
           return context.put(key, value);
     }
     /* 对象方法 end */
}


这里仅仅存储了request和response,你还可以自行存储国际化信息,容器信息,或者执行Action的上下文信息等.
再一次说明的是request和response是线程安全的,但是你要达到不通过继承或者传参等方式可以在任何地方都能获得request资源,用threadLocal是最好的选择。

调用方式如下(请对照源代码)
 //注入Action Context
          Map<String, Object> contextMap= new HashMap<String, Object>();
          contextMap.put(ActionContext. HTTPREQUEST, request);
          contextMap.put(ActionContext. HTTPRESPONSE,response);
          ActionContext. setContext(new ActionContext(contextMap));

ThreadLocal存储会耗费不小的资源,所以用完必须清除掉,为了保险起见,在finally块里调用清除代码:
finally{
           //释放上下文资源
          ActionContext. setContext(null);
     }


以后在任何请求范围内都可以通过ActionContext.getRequest()和ActionContext.getResponse()得到请求资源或响应
到此我们基本的配置跳转已算完成,可以自行测试一下了。

By 阿飞哥 转载请说明
腾讯微博:http://t.qq.com/duyunfeiRoom
新浪微博:http://weibo.com/u/1766094735
原文地址:http://duyunfei.iteye.com/blog/1773693
分享到:
评论

相关推荐

    Java Web开发实践教程源码

    Spring MVC作为Java Web开发中常用的框架,提供了一种模块化、松耦合的方式来组织和控制应用程序的流程。 此外,源码还可能包含数据库连接、DAO(数据访问对象)设计模式、JDBC(Java Database Connectivity)操作...

    Extjs4学习指南

    #### 1. Extjs初步 ##### 1.1 获取Extjs - **下载Extjs**:可以通过官方网站http://extjs.org.cn/获取Extjs的发布包和其他支持资源。 ##### 1.2 搭建学习环境 - **环境准备**:确保已安装MyEclipse和Tomcat。...

    subunit-devel-1.4.0-14.el8.x64-86.rpm.tar.gz

    1、文件说明: Centos8操作系统subunit-devel-1.4.0-14.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf subunit-devel-1.4.0-14.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm

    TIA-Portal-V19-HSP.zip

    TIA_Portal_V19_HSP.zip

    自己搭建的无人机跟踪实验,主要讲软件,硬件的需要等等,为初学者提供学习建议及需要学习的内容,讲解使用到的代码等.zip

    自己搭建的无人机跟踪实验,主要讲软件,硬件的需要等等,为初学者提供学习建议及需要学习的内容,讲解使用到的代码等.zip

    stunnel-5.56-5.el8-3.x64-86.rpm.tar.gz

    1、文件说明: Centos8操作系统stunnel-5.56-5.el8_3.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf stunnel-5.56-5.el8_3.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm

    西门子PLC与ABB变频器Modbus通讯实战:参数读写、启停控制及触摸屏集成

    内容概要:本文详细介绍了西门子S7-1200 PLC与ABB ACS510变频器通过Modbus协议进行通讯的方法。首先讲解了硬件连接,包括RS485通讯线的正确接法和终端电阻的使用。接着深入探讨了PLC程序的设计,涵盖Modbus主站的初始化、参数读写(如频率设定、启停控制)、以及错误处理方法。同时,提供了触摸屏(WinCC Basic)的操作指导,包括变量关联、按钮绑定和数据显示。最后给出了常见问题的解决方案,确保通讯稳定可靠。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是需要进行PLC与变频器通讯调试的工作人员。 使用场景及目标:适用于需要将西门子PLC与ABB变频器进行Modbus通讯的应用场合,帮助工程师快速掌握通讯配置、参数设置、启停控制及触摸屏集成的具体步骤,提高工作效率并减少调试时间。 其他说明:文中提供了详细的代码示例和注意事项,有助于读者更好地理解和应用相关技术。此外,强调了硬件检查的重要性,避免因接线问题导致的通讯失败。

    Zwift离线版-Windows端教程

    Zwift离线版-Windows端教程

    2023-04-06-项目笔记 - 第四百五十一阶段 - 4.4.2.449全局变量的作用域-449 -2025.03.28

    2023-04-06-项目笔记-第四百五十一阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.449局变量的作用域_449- 2025-03-28

    十六届蓝桥杯单片机模拟赛资源包.zip

    学习资料:十六届蓝桥杯单片机模拟赛资源包

    机器人控制领域的超轨双光与RIC二光PID程序解析及其应用

    内容概要:本文详细解析了超轨双光PID和RIC二光PID两种开源控制程序的设计思路和实现细节。首先介绍了超轨双光PID程序的核心计算方法,包括PID计算、误差获取以及参数整定等方面的内容。接着探讨了RIC二光PID程序的独特之处,如误差合成、参数自适应和遗忘因子的应用。文中强调了积分项防爆处理、微分项灵敏度提升、传感器布局优化等关键技术点,并提供了调试建议和实践经验。此外,还讨论了增量式PID结构、状态观测器、PWM占空比转换等实用技巧。 适合人群:对机器人控制领域感兴趣的初学者和技术爱好者,尤其是希望深入了解PID控制算法的人群。 使用场景及目标:适用于需要理解和实现PID控制算法的实际工程项目,特别是涉及双光传感器的小车控制系统。目标是帮助读者掌握PID控制的基本原理和高级优化技巧,提高系统的稳定性和响应速度。 其他说明:文中提供的代码片段和调试建议非常实用,建议读者在实践中结合这些内容进行实验和调试,以便更好地理解PID控制的工作机制。

    putty0.80中文设置文件本地目录保存版

    putty0.80CN-X64本地记录

    subunit-1.4.0-14.el8.x64-86.rpm.tar.gz

    1、文件说明: Centos8操作系统subunit-1.4.0-14.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf subunit-1.4.0-14.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm

    基于Matlab/Simulink的IEEE RBTS BUS4电力系统仿真模型构建与故障分析

    内容概要:本文详细介绍了如何利用Matlab 2016a的Simulink工具箱搭建IEEE RBTS BUS4标准电力系统仿真模型。首先,文章讲解了系统的基本结构和主要元件的参数设置方法,如主变压器、母线、输电线路等。其次,针对测量模块的布置进行了指导,确保能够精确获取电压和电流数据。再次,探讨了故障注入的方法及其对系统的影响,包括三相短路故障的设置和效果分析。此外,还讨论了分布式电源(如光伏)的接入方式以及其对系统稳定性的影响。最后,提供了批量仿真和数据采集的一些实用技巧。 适合人群:从事电力系统研究和技术开发的专业人士,尤其是有一定Matlab/Simulink使用经验的研究人员。 使用场景及目标:①帮助研究人员快速掌握IEEE RBTS BUS4标准系统的建模方法;②提供详细的故障注入和分布式电源接入案例,便于理解和应用;③通过具体实例展示如何优化系统性能,提高仿真精度。 其他说明:文中不仅包含了具体的参数设定和代码片段,还有许多实践经验分享,有助于读者更好地理解和运用所学知识进行实际项目开发。

    zhengquan看看看咯

    zhengquan看看看咯

    计算机概论教学课件.pdf

    计算机概论教学课件.pdf

    LanQiaoCup-master-蓝桥杯刷题项目

    LanQiaoCup-master-蓝桥杯刷题项目

    用matlab实现的mpc模型预测控制,用matlab的quadprog函数实现了线性mpc函数双积分控制,倒立摆控制,车辆云动学模型控制,车辆动力学模型控制

    matlab

    单片机设计 基于C语言的单片机红外遥控系统设计与实现的详细项目实例(含完整的硬件电路设计,程序设计、GUI设计和代码详解)

    内容概要:本文档详细介绍了一款基于C语言的单片机红外遥控系统的设计与实现。项目旨在通过单片机平台实现对家电设备的高效、稳定、低成本的红外遥控控制。系统设计涵盖了硬件电路设计、软件架构、信号处理、功耗管理、抗干扰设计等方面。文中详细介绍了各个功能模块的具体实现,包括系统初始化、红外信号接收与解码、控制逻辑、红外信号发射等。此外,文档还探讨了系统的可扩展性,提出了多项创新和技术改进的方向,如多设备控制、语音识别、无线网络控制、自学习功能等。 适合人群:具备一定单片机基础知识的研发人员,特别是对嵌入式系统设计、红外通信技术感兴趣的工程师。 使用场景及目标:①学习单片机与红外遥控技术的基础理论和实际应用;②掌握嵌入式系统设计的方法和技巧,特别是在信号处理、功耗优化等方面的实践经验;③为智能家居、家庭娱乐系统等领域的产品开发提供参考。 其他说明:文档不仅提供了详细的硬件电路设计和软件代码实现,还包括了GUI设计的要求和具体实现步骤。此外,文档还强调了系统的可扩展性和未来改进方向,如集成更多传感器、云平台与大数据分析、机器学习等先进技术,以提升系统的智能化水平。

    5G IPRAN基站业务组网及关键技术解析

    内容概要:本文详细介绍了5G IPRAN(IP Radio Access Network)基站业务组网的技术背景、关键技术和具体配置。主要内容涵盖IPRAN的基本概念及其在5G时代的必要性,新型IPRAN设备的功能改进和支持的新技术(如SR、FlexE等),以及具体的组网架构和技术细节,包括但不限于DCN自通、PW+L3VPN组网、FlexE配置、Telemetry技术、Segment Routing、EVPN实现方式、MPLS OAM等。此外,文章还深入探讨了IPRAN基站的流量走向、高可靠性和配置要点,特别是A设备、B设备和ER设备的具体配置步骤。 适合人群:具备一定网络工程基础的专业人士,尤其是从事5G网络建设和维护的技术人员。 使用场景及目标:帮助技术人员理解和实施5G IPRAN基站业务组网,确保网络架构的高效性和稳定性,满足5G网络大带宽、低延迟的要求。 其他说明:本文不仅提供了理论知识,还附带了大量的配置示例,便于读者在实践中应用。

Global site tag (gtag.js) - Google Analytics