appfuse文档(五)--创建Action和JSP

本文介绍了在AppFuse框架中创建Action和JSP的详细步骤,包括为Person添加XDoclet Tags生成PersonForm、使用XDoclet创建JSP骨架、创建并测试PersonAction等。还提及了AppGen工具的使用方法,以及如何清理JSP使其符合规格,最后介绍了可选的Canoo WebTest测试。

创建ActionJSP

本章将向你展示怎样创建ActionJSP

这部分内容依赖Part II: 创建Manager

关于本章

本章将向你展示怎样创建一个StrutsAction, 一个JUnit Test (使用StrutsTestCase ),和一个包含formJSP。我们创建的Action将和在上一章中创建的PersonManager进行交互。

AppFuse使用Struts 作为它默认的Web框架。在1.6中,你还可以使用Spring 或者 WebWork 。在1.71.8中将会把TapestryJSF集成进来。

我们首先创建一个Struts ActionJSP

内容

·   [1] Person添加XDoclet Tags来产生PersonForm

·   [2] 使用XDoclet 来创建JSPskeleton(骨架)

·   [3] 创建测试PersonAction PersonActionTest

·   [4] 创建PersonAction

·   [5] 运行PersonActionTest

·   [6] 清理JSP,使它合乎要求 [make it presentable]

·   [7] 创建测试ActionCanoo WebTest[可以像浏览器一样测试Action]

AppGen

AppGen 1.6.1 的一部分,它是基于Lance Lavandowska Ben Gill 的工具产生的. 起初,我不想添加像这个B/S结构的程序产生的代码特征(表和POJO之间、DAOManager之间的一对一关系)。我的大部分的工程中,我使用的DAOManager要比POJO少得多。

默认情况下, AppGen将只产生Actions/Controllers, Action/Controller Tests, 测试数据, i18n key JSP.它也会为你配置好Action/Controller。它使用通用的BaseManagerBaseDAOHibernate (被配置为"manager""dao") 来减少产生的文件数。我也认识到有时候你可能需要产生所有的DAO Manager类及它们的测试类,所以我添加了一个可以达到这个目的的选项。

安装完框架后,如果你想使用AppGen工具,请按照下面的步骤进行:

1. 先安装框架,在model目录中创建你的POJO(ltf:POJOhibernateStruts的标签都要添加,然后ant setup”)

2. 然后配置applicationContext-hibernate.xml 配置映射文件

<property name="mappingResources"
    <list> 
        <value>org/appfuse/model/Person.hbm.xml</value> 
        <value>org/appfuse/model/Role.hbm.xml</value> 
        <value>org/appfuse/model/User.hbm.xml</value> 
        <value>org/appfuse/model/UserCookie.hbm.xml</value>  
    </list> 
</property> 

3. 进入到目录extras/appgen中,
然后运行"ant -Dmodel.name=Person -Dmodel.name.lowercase=person"。本例中,类Person应当已经存在你的"model"包里面了。这将为你产生所有你在这个手册里面创建的所有的文件。

4. 运行"ant install-detailed "来安装产生的文件(ltf:实际上就是将产生的文件复制到源代码树的相应位置)。你可以运行
"ant install-detailed -Dmodel.name=Person -Dmodel.name.lowercase=person"

5. 修改personForm.jsp,将“id”属性变为隐藏域(hidden)

6. 进入cd ../..”, 运行“ant setup”以产生新的struts-config.xml等文件。

7. 修改JSP文件,如果当前JSP中没有必须填的字段,则要将*Form页面最下部的html:javascript代码注释掉。

8. 运行“ant deploy

注意: 如果你不想产生所有的DAO/Manager/Test, 运行"ant install " 代替"ant install-detailed "。在安装文件之前,要保证所有文件已经被创建到了目录extras/appgen/build/gen中。如果你只是想测试这个工具,你可以进入这个目录,然后运行"ant test"

警告: 我建议你在做这些之前备份你的工程,我已经测试了这个工具,它工作的很好,但它会更改你的源文件的目录树结构。

使用"lowercase"参数的原因是使产生的JSP的文件名开头的字母为小写的。

这个工具将自动产生CRUD代码,这样可以使你将精力集中在业务逻辑和美化界面上。

Person添加XDoclet Tags来产生PersonForm

现在我们要生成供Web层使用的PersonForm对象。我们为Person.java需要添加Xdoclet标签来创建ActionForm。在Person.java 文件的JavaDoc, 添加下面的@struts.form标签(可以参考 User.java):

* @struts.form include-all="true" extends="BaseForm"

我们继承org.appfuse.webapp.form.BaseForm,因为它有toString()方法,它可以使我们调用log.debug(formName)来打印一个窗体对象的友好的视图.

如果你重命名 "org.appfuse" packages"com.company"或者其他的方式,那么你的默认包内没有model类,你要在@struts.form标签部分添加完整类名

(包括包名)[fully-qualify]来引用org.appfuse.webapp.form.BaseForm

使用XDoclet 来创建JSPskeleton(骨架)

这一步,我们将生成skeleton或者用于显示PersonForm信息的JSP. 我说生成的是skeleton是因为它只是<form>自己。它将包含表的数据和对应PersonForm.java中每个属性的Struts标签<html:text>。我们使用的工具只是一个类(FormTagsHandler.java) 2XDoclet模板(FormKeys.xdtStrutsForm_jsp.xdt),所有这些文件位于目录extras/viewgen中。

警告: "viewgen" AppFuse 1.6.1 中已经是不建议使用的工具了,在1.7中将被删除。appgen 将提供同样的功能。

下面是一个生成JSP和窗体元素的Label的属性文件(properties file)的简单步骤:

·   执行ant compile根据Person.java产生PersonForm.java(build/web/gen/)

·   使用命令行cmd”, 进入到目录"extras/viewgen"

·   执行ant -Dform.name=PersonForm将在extras/viewgen/build中产生3个文件:

·       PersonForm.properties (form元素的label)

·       PersonForm.jsp (用来查看一个PersonJSP的骨架程序)

·       PersonFormList.jsp (或是PersonList,查看People列表的JSP的骨架程序)

·   复制PersonForm.properties的内容到 web/WEB-INF/classes/ApplicationResources_en.properties.
例:以下内容要加入到ApplicationResources_en.properties文件:

# -- person form --

personForm.firstName=First Name

personForm.id=Id

personForm.lastName=Last Name

·   复制PersonForm.jspweb/pages/personForm.jsp.
复制PersonFormList.jsp(PersonList.Jsp) web/pages/personList.jsp.
注意:每个新文件的名字第一个字符都是小写。

"pages"目录下的文件在部署时将会放入"WEB-INF/pages"目录中。这样可以使用容器提供的安全机制去保护WEB-INF中的文件。这只针对客户的请求,不会阻止Struts ActionServletforward。将JSP放入WEB-INF中,以确保他们只能通过Action被访问。这样安全的问题将被转移到Action中。这样可以更有效率,同时也是它从表现层中脱离出来。

AppFuseWeb程序的安全机制指定所有*.html模式的页面都应该被保护。 (除了/signup.html /passwordHint.html)。这样确保客户端必须通过Action才能跳转到在pages目录下的JSP

如果你使用Eclipse, 你可能要"refresh"工程才能看到PersonForm。它位于目录build/web/gen中。这是在Eclipse中看到、导入PersonForm的唯一途径, 因为它被 XDoclet产生,并且不在你的常规的源代码的目录树中。你可以在这里找到它:build/web/gen/org/appfuse/webapp/form/PersonForm.java.

BaseAction 中,你可以注册其他的Converters (如: DateConverter )所以 BeanUtils.copyProperties知道怎样去convert Strings Objects.如果你有POJO的列表 (如:父子关系),你将需要使用convertLists(java.lang.Object)方法进行手工转换。

NOTE: 如果你想为一个特殊页指定CSS,你可以添加<body id="pageName"/> 到文件的顶部。这将被SiteMesh捕捉到并会被放如最终的页面中。这样你就可以像下面这样一页一页的定义你的CSS:

body#pageName element.class { background-color: blue }

·   ApplicationResources_en.properties中添加JSP文件的 titleheadingKey

在生成的JSP,2Key,用于title (浏览器窗口的顶部)header (页头).
我们现在需要添加这2key (personDetail.titlepersonDetail.heading) ApplicationResources_en.properties文件中.

打开web/WEB-INF/classes/ApplicationResources_en.properties
然后将下面的内容添加到文件底部:

# -- person detail page --

personDetail.title=Person Detail

personDetail.heading=Person Information

在上文中我们刚刚添加"personForm.*" key到这个文件,为什么我既使用personForm又使用personDetail? 最好的解释是它很好的分离了页面上的form labeltext。另一个原因是所有的*Form.*给我们一个很好的数据库所有字段的表示方法。

最近,我有一个客户,他希望数据库中的所有字段都应该是可以查询的。这很好实现。我只在ApplicationResources.properties文件中搜寻包含"Form."Key,然后把它们放到下拉列表中。用户能够输入查询值,然后选择一个他希望搜索的列。我很高兴我将FormDetail区分开了!

创建测试PersonAction PersonActionTest

为测试PersonAction 我们创建一个StrutsTestCase,我们在test/web/**/action 目录中创建PersonActionTest.java.

实际上, 我常常复制另存为一个已经有的ActionTest (i.e. UserActionTest). [P]erson覆盖 [Uu]se

如果你的确复制了UserActionTest,确保已经改变UserFormExPersonForm UserFormEx 是一个 UserForm的扩展,它有用于 Rolessetter,返回String[] 因为 UserForm已经产生,User.java对象中这样做不是很可行的。

package org.appfuse.webapp.action;

import org.appfuse.Constants;
import org.appfuse.webapp.form.PersonForm;

public class PersonActionTest extends BaseStrutsTestCase {
    
    public PersonActionTest(String name) {
        super(name);
    }

    public void testEdit() throws Exception {
        setRequestPathInfo("/editPerson");
        addRequestParameter("method""Edit");
        addRequestParameter("id""1");
        actionPerform();

        verifyForward("edit");
        assertTrue(request.getAttribute(Constants.PERSON_KEY) != null);
        verifyNoActionErrors();
    }

    public void testSave() throws Exception {
        setRequestPathInfo("/editPerson");
        addRequestParameter("method""Edit");
        addRequestParameter("id""1");

        actionPerform();

        PersonForm personForm =
            (PersonForm) request.getAttribute(Constants.PERSON_KEY);
        assertTrue(personForm != null);
        
        setRequestPathInfo("/savePerson");
        addRequestParameter("method""Save");

        // update the form from the edit and add it back to the request
        personForm.setLastName("Feltz");
        request.setAttribute(Constants.PERSON_KEY, personForm);

        actionPerform();

        verifyForward("edit");
        verifyNoActionErrors();
    }

    public void testRemove() throws Exception {
        setRequestPathInfo("/editPerson");
        addRequestParameter("method""Delete");
        addRequestParameter("id""2");
        actionPerform();

        verifyForward("mainMenu");
        verifyNoActionErrors();
    }
}

你要往src/dao/**/Constants.java中添加一个变量PERSON_KEY.
名字"personForm"要和struts-config.xml中配置的form名字一样.

    /**
     * The request scope attribute that holds the person form.
     */
    public static final String PERSON_KEY = "personForm";

如果你试着运行这个测试, 你将得到很多NoSuchMethodErrors错误
所以我们要在PersonAction类中定义edit, save, delete方法

创建PersonAction

src/web/**/action, 创建PersonAction.java。内容如下:

package org.appfuse.webapp.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import org.appfuse.model.Person;
import org.appfuse.service.PersonManager;
import org.appfuse.webapp.form.PersonForm;

/**
 * @struts.action name="personForm" path="/editPerson" scope="request"
 *  validate="false" parameter="method" input="mainMenu"
 */
public final class PersonAction extends BaseAction {
    
    public ActionForward cancel(ActionMapping mapping, ActionForm form,
                                HttpServletRequest request,
                                HttpServletResponse response)
    throws Exception {
        return mapping.findForward("mainMenu");
    }

    public ActionForward delete(ActionMapping mapping, ActionForm form,
                                HttpServletRequest request,
                                HttpServletResponse response)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'delete' method");
        }

        ActionMessages messages = new ActionMessages();
        PersonForm personForm = (PersonForm) form;

        // Exceptions are caught by ActionExceptionHandler
        PersonManager mgr = (PersonManager) getBean("personManager");
        mgr.removePerson(personForm.getId());

        messages.add(ActionMessages.GLOBAL_MESSAGE,
                     new ActionMessage("person.deleted",
                                       personForm.getFirstName() + ' ' +
                                       personForm.getLastName()));

        // save messages in session, so they'll survive the redirect
        saveMessages(request.getSession(), messages);

        return mapping.findForward("mainMenu");
    }

    public ActionForward edit(ActionMapping mapping, ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'edit' method");
        }

        PersonForm personForm = (PersonForm) form;

        // if an id is passed in, look up the user - otherwise
        // don't do anything - user is doing an add
        if (personForm.getId() != null) {
            PersonManager mgr = (PersonManager) getBean("personManager");
            Person person = mgr.getPerson(personForm.getId());
            personForm = (PersonForm) convert(person);
            updateFormBean(mapping, request, personForm);
        }

        return mapping.findForward("edit");
    }

    public ActionForward save(ActionMapping mapping, ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'save' method");
        }

        // Extract attributes and parameters we will need
        ActionMessages messages = new ActionMessages();
        PersonForm personForm = (PersonForm) form;
        boolean isNew = ("".equals(personForm.getId()));

        if (log.isDebugEnabled()) {
            log.debug("saving person: " + personForm);
        }

        PersonManager mgr = (PersonManager) getBean("personManager");
        Person person = (Person) convert(personForm);
        mgr.savePerson(person);

        // add success messages
        if (isNew) {
            messages.add(ActionMessages.GLOBAL_MESSAGE,
                         new ActionMessage("person.added",
                                           personForm.getFirstName() + " " +
                                           personForm.getLastName()));

            // save messages in session to survive a redirect
            saveMessages(request.getSession(), messages);

            return mapping.findForward("mainMenu");
        else {
            messages.add(ActionMessages.GLOBAL_MESSAGE,
                         new ActionMessage("person.updated",
                                           personForm.getFirstName() + " " +
                                           personForm.getLastName()));
            saveMessages(request, messages);

            return mapping.findForward("edit");
        }
    }
}

从上面的代码你可以注意到: 有很多调用convert 一个PersonForm或者Person对象。这个convert BaseAction.java中的一个方法,它内部调用ConvertUtil.convert()方法,并使用BeanUtils.copyProperties 将进行如下转换:POJO ActionForm,将ActionForm POJO

现在,你要添加edit forwardsavePerson action-mapping PersonActionTest中将引用它们。 为了达到这个目的, 我们要添加Xdoclet标签到 PersonAction.java的顶部. 如果你在上面的类声明中所有的都正确,你应该已经有用于editPerson action-mappingXDoclet标签了,但我仍然要把它列在这里,以便你能够看到这个类顶部的所有的XDoclet标签。

/**
 * @struts.action name="personForm" path="/editPerson" scope="request"
 *  validate="false" parameter="method" input="mainMenu"
 
 * @struts.action name="personForm" path="/savePerson" scope="request"
 *  validate="true" parameter="method" input="edit"
 
 * @struts.action-forward name="edit" path="/WEB-INF/pages/PersonForm.jsp"
 */
public final class PersonAction extends BaseAction {

EditPersonsavePerson action-mapping的主要区别是savePerson的校验已经打开( validation="true") 。注意:"input"必须是一个forward, 而不能是一个path (如: /editPerson.html)。如果你想让editsave都使用save path (ltf:path?),也可以的。只要确保两者的 validate="false",再在你的"save"方法中调用form.validate() ,然后适当的处理错误。

这里有几个用来显示操作成功消息的key,你要添加到目录web/WEB-INF/classes下的ApplicationResources_en.properties文件里。打开这个文件,添加如下内容:

我通常添加到# -- success messages –-“注释下面.

person.added=Information for <strong>{0}</strong> has been added successfully.

person.deleted=Information for <strong>{0}</strong> has been deleted successfully.

person.updated=Information for <strong>{0}</strong> has been updated successfully.

你应该使用一般的added, deletedupdated messages,无论你怎么工作,它都可以避免因为每改变一个实体就要将消息改变。

你可能注意到你用来调用PersonManager的代码和用在PersonManagerTest中的是一样。PersonActionPersonManagerTest都是PersonManagerImpl的“客户端”, 这样感觉很完美。

所有一切几乎都完成了,让我们运行测试吧!

运行PersonActionTest

如果你在看PersonActionTest, 所有的测试都依赖一条记录id=1的数据库记录(testRemove依赖id=2的记录), 所以要添加示例数据文件(metadata/sql/sample-data.xml). 我已经把它们添加到下面了表的顺序并不重要,因为它目前没有和任何其他的表关联。
(
ltf:如果这个表和其他的表用外键/触发器关联,则必须注意表创建的顺序和数据添加的顺序)

  <table name='person'>

    <column>id</column>

    <column>first_name</column>

    <column>last_name</column>

    <row>

      <value>1</value>

      <value>Matt</value>

      <value>Raible</value>

    </row>

    <row>

      <value>2</value>

      <value>James</value>

      <value>Davidson</value>

    </row>

  </table>

在我们的所有测试被执行之前,DBUnit会首先装载这个文件, 所以这个记录可以被PersonActionTest使用。

现在你执行ant test-web -Dtestcase=PersonAction一切都应该按照计划进行.
在你执行这个命令前,要确保Tomcat没有运行。

BUILD SUCCESSFUL
Total time: 1 minute 21 seconds

清理JSP,使JSP符合规格(presentable)

现在我们开始清理personForm.jsp,我们要使"id"变成一个hidden”. web/pages/personForm.jsp中删除下面的代码块:

    <tr>
        <th>
            <appfuse:label key="personForm.id"/>
        </th>
        <td>
            <html:text property="id" styleId="id"/>
            <html:errors property="id"/>
        </td>
    </tr>

<table>标记之前添加下面的内容:

<html:hidden property="id"/>

你应该改变<html:form>action"savePerson",这样当你保存数据时,校验将被打开,同样, 改变focus属性,从focus=""focus="firstName",这样页面打开后,光标停留在firstName字段(这是使用JavaScript实现的).

现在执行ant db-load deploy, 然后启动Tomcat,最后打开浏览器,输入 http://localhost:8080/appfuse/editPerson.html?id=1 , 你应该看到如下界面:

注意:如果你改变了web目录下的任何文件,要使用deploy-web target.
否则,使用deploy 编译并部署

最后,为了使这个页面更加友好,你可能想在form顶部向你的用户显示提示消息,这个很容易实现。
personForm.jsp顶部使用<fmt:message>就可以了。
 
[可选] 创建测试ActionCanoo WebTest

这个指南最后一步使创建一个Canoo WebTest 用来测试JSP.

我之所以说这一步是可选的,是因为你可以使用浏览器达到同样目的。

你可以使用下面的URL来测试已经添加的不同的action, 编辑和保存一个用户。

·   添加 - http://localhost:8080/appfuse/editPerson.html

·   修改 - http://localhost:8080/appfuse/editPerson.html?id=1 (确信你已经首先运行了ant db-load)

·   删除 - http://localhost:8080/appfuse/editPerson.html?method=Delete&id=1 (or edit and click on the Delete button)

·   保存单击 edit ,然后单击Save按钮。

Canoo测试相当平滑,配置它们在XML文件中十分简单。我们现在要为add, edit, savedelete添加测试用例,打开test/web/web-tests.xml,然后添加下面的XML。你将会注意到这个片断有一个叫PersonTests的任务,它运行所有相关的测试。

I use CamelCase target names (vs. the traditional lowercase, dash-separated) because when you're typing -Dtestcase=Name, I've found that I'm used to doing CamelCase for my JUnit Tests.

<!-- runs person-related tests -->
<target name="PersonTests"
    depends="EditPerson,SavePerson,AddPerson,DeletePerson"
    description="Call and executes all person test cases (targets)">
    <echo>Successfully ran all Person JSP tests!</echo>
</target>

<!-- Verify the edit person screen displays without errors -->
<target name="EditPerson"
    description="Tests editing an existing Person's information">
    <canoo name="editPerson">
        &config;
        <steps>
            &login;
            <invoke stepid="click Edit Person link" url="/editPerson.html?id=1"/>
            <verifytitle stepid="we should see the personDetail title"
                text="${webapp.prefix}${personDetail.title}"/>
        </steps>
    </canoo>
</target>

<!-- Edit a person and then save -->
<target name="SavePerson"
    description="Tests editing and saving a user">
    <canoo name="savePerson">
        &config;
        <steps>
            &login;
            <invoke stepid="click Edit Person link" url="/editPerson.html?id=1"/>
            <verifytitle stepid="we should see the personDetail title"
                text="${webapp.prefix}${personDetail.title}"/>
            <setinputfield stepid="set lastName" name="lastName" value="Canoo"/>
            <clickbutton label="Save" stepid="Click Save"/>
            <verifytitle stepid="Page re-appears if save successful"
                text="${webapp.prefix}${personDetail.title}"/>
        </steps>
    </canoo>
</target>

<!-- Add a new Person -->
<target name="AddPerson"
    description="Adds a new Person">
    <canoo name="addPerson">
        &config;
        <steps>
            &login;
            <invoke stepid="click Add Button" url="/editPerson.html"/>
            <verifytitle stepid="we should see the personDetail title"
                text="${webapp.prefix}${personDetail.title}"/>
            <setinputfield stepid="set firstName" name="firstName" value="Abbie"/>
            <setinputfield stepid="set lastName" name="lastName" value="Raible"/>
            <clickbutton label="${button.save}" stepid="Click button 'Save'"/>
            <verifytitle stepid="Main Menu appears if save successful"
                text="${webapp.prefix}${mainMenu.title}"/>
            <verifytext stepid="verify success message"
                text="Information for &lt;strong&gt;Abbie Raible&lt;/strong&gt; has been added successfully."/>
        </steps>
    </canoo>
</target>

<!-- Delete existing person -->
<target name="DeletePerson"
    description="Deletes existing Person">
    <canoo name="deletePerson">
        &config;
        <steps>
            &login;
            <invoke stepid="click Edit Person link" url="/editPerson.html?id=1"/>
            <clickbutton label="${button.delete}" stepid="Click button 'Delete'"/>
            <verifytitle stepid="display Main Menu" text="${webapp.prefix}${mainMenu.title}"/>
            <verifytext stepid="verify success message"
                text="Information for &lt;strong&gt;Matt Canoo&lt;/strong&gt; has been deleted successfully."/>
        </steps>
    </canoo>
</target>

添加完这些后,当Tomcat运行时,你应该可以运行ant test-canoo -Dtestcase=PersonTests,或者,如果你想start/stop Tomcat,执行ant test-jsp -Dtestcase=PersonTests当所有Canoo tests被运行(包括PersonTests),添加它作为"run-all-tests"任务的一个必需的依赖。

你应该注意到如果使用Canoo,客户端没有日志,如果你想知道正在干什么,你可以添加下面的文字到每个任务的末端的</canoo> </target>之间。

<loadfile property="web-tests.result"

    srcFile="${test.dir}/data/web-tests-result.xml"/>

<echo>${web-tests.result}</echo>

BUILD SUCCESSFUL
Total time: 11 seconds


下一步: Part IV: 添加校验和菜单 personForm 添加校验逻辑,使 firstName lastName 是必填字段,并且添加一个屏幕列表数据库中所有人的记录 .
代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制与早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置与故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单中增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单中已有的项目。 bootcfg /disableredirect 在启动引导程序中禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...
代码下载链接: https://pan.quark.cn/s/fc524f791b68 AA制程,即Active Alignment,被理解为主动对准,是一种用于确定零部件装配中相对位置的方法。在摄像头封装阶段,涉及图像传感器、镜座、马达、镜头、线路板等多个部件的重复组装,而传统的封装设备如CSP及COB等,均是依据设备设定的参数进行零部件的移动装配,因而零部件的叠加误差会逐渐增大,最终在摄像头上表现为拍照最清晰的位置可能偏离画面中心、四边清晰度不均等现象。伴随智能手机其他高端电子产品的普及,摄像头模组的性能正日益受到重视。高分辨率、卓越的低光表现以及稳定视频输出是现代用户所期望的。在摄像头模组的制造环节,各部件的精准定位对成像质量具有决定性作用。因此,一种名为“AA制程”(Active Alignment)的前沿技术被开发出来,成为摄像头精密对准的核心技术。 AA制程,即Active Alignment,是一种在摄像头封装过程中应用的主动对准方法。该方法在多个组件装配阶段发挥作用,涵盖图像传感器、镜座、马达、镜头线路板等部件。传统的封装方式,例如CSP(Chip Scale Package)COB(Chip On Board),依赖于设备预设的参数进行组装,但随着组件数量的增加,误差也会累积,最终影响摄像头的表现。例如在成像质量上可能出现中心位置偏移、四角清晰度不一致等问题。 AA制程技术的核心在于实时监测与主动调整。在组装过程中,它借助先进的检测设备持续监控半成品的状态,并根据实时信息对组装部件进行精确修正,从而显著降低装配误差。通过这种技术,能够确保摄像头模组中各组件的相对位置准确无误,从而使得最终的成像效果更加稳定,特别是在中心区域四角的清晰度上...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值