webapp文本编辑器_Project Student:维护Webapp(可编辑)

webapp文本编辑器

这是Project Student的一部分。 其他职位包括带有Jersey的 Web服务 客户端,带有Jersey的 Web服务服务器 , 业务层 , 带有Spring数据的持久性 ,分片集成测试数据 , Webservice集成 , JPA标准查询和维护Webapp(只读) 。

上次我们创建了一个简单的Web应用程序,使我们可以快速浏览数据库。 它的功能非常有限–主要目标是将整个系统(从Web浏览器到数据库)的整个系统组合在一起。 这次我们添加了实际的CRUD支持。

这篇文章是从Jumpstart网站大量借用的,但有很大的不同。 有很多代码,但是很容易重用。

局限性

  • 用户身份验证 –尚未进行身份验证的工作。
  • 加密 -尚未对通信进行加密。
  • 分页 –尚未做出任何努力来支持分页。 Tapestry 5组件将显示分页外观,但始终包含相同的第一页数据。
  • 错误消息 –将显示错误消息,但服务器端错误目前尚无信息。
  • 跨站点脚本(XSS) –尚未做出任何努力来防止XSS攻击。
  • 国际化 –尚未做出任何努力来支持国际化。

目标

我们需要标准的CRUD页面。

首先,我们需要能够创建一门新课程。 当我们没有任何数据时,我们的课程列表应包含一个链接作为默认消息。 (第一个“创建...”是一个单独的元素。)

课程列表Chromium_008

现在,创建页面具有多个字段。 代码唯一地标识一门课程,例如CSCI 101,其名称,摘要和说明应不言自明。

课程编辑器Chromium_006

创建成功后,我们将进入评论页面。

课程编辑器Chromium_002

如果需要进行更改,然后返回更新页面。

课程编辑器Chromium_004

任何时候我们都可以返回列表页面。

课程列表Chromium_001

在删除记录之前,系统会提示我们进行确认。

Course-List-Chromium_005

最后,我们可以显示服务器端错误,例如,即使当前消息非常无用,也要显示唯一字段中的重复值。

课程编辑器Chromium_007

我们也有客户端错误检查,尽管我在这里没有显示。

Index.tml

我们从索引页面开始。 这类似于我们在上一篇文章中看到的内容。

Tapestry 5具有三种主要类型的链接。 页面链接映射到标准HTML链接。 一个ActionLink的是直接由相应的类,例如,Index.javaIndex.tml模板处理。 最后,事件链接将事件注入挂毯引擎内的正常事件流。 我所有的链接都转到一个密切相关的页面,所以我使用一个动作链接。

<html t:type="layout" title="Course List"t:sidebarTitle="Framework Version"xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"xmlns:p="tapestry:parameter"><t:zone t:id="zone">   <p>"Course" page</p><t:actionlink t:id="create">Create...</t:actionlink><br/><t:grid source="courses" row="course" include="code, name,creationdate" add="edit,delete"><p:codecell><t:actionlink t:id="view" context="course.uuid">${course.code}</t:actionlink></p:codecell><p:editcell><t:actionlink t:id="update" context="course.uuid">Edit</t:actionlink></p:editcell><p:deletecell><t:actionlink t:id="delete" context="course.uuid" t:mixins="Confirm" t:message="Delete ${course.name}?">Delete</t:actionlink></p:deletecell><p:empty><p>There are no courses to display; you can <t:actionlink t:id="create1">create</t:actionlink> one.</p></p:empty></t:grid></t:zone><p:sidebar><p>[<t:pagelink page="Index">Index</t:pagelink>]<br/>[<t:pagelink page="Course/Index">Courses</t:pagelink>]</p></p:sidebar></html>

确认混入

Index.tml模板在删除操作链接上包含一个“ mixin”。 它使用javascript和Java的混合显示弹出消息,要求用户确认他要删除课程。

此代码直接来自Jumpstart和Tapestry网站。

// from http://jumpstart.doublenegative.com.au/
Confirm = Class.create({initialize: function(elementId, message) {this.message = message;Event.observe($(elementId), 'click', this.doConfirm.bindAsEventListener(this));},doConfirm: function(e) {// Pop up a javascript Confirm Box (see http://www.w3schools.com/js/js_popup.asp)if (!confirm(this.message)) {e.stop();}}
})// Extend the Tapestry.Initializer with a static method that instantiates a Confirm.Tapestry.Initializer.confirm = function(spec) {new Confirm(spec.elementId, spec.message);
}

相应的Java代码是

// from http://jumpstart.doublenegative.com.au/
@Import(library = "confirm.js")
public class Confirm {@Parameter(name = "message", value = "Are you sure?", defaultPrefix = BindingConstants.LITERAL)private String message;@Injectprivate JavaScriptSupport javaScriptSupport;@InjectContainerprivate ClientElement clientElement;@AfterRenderpublic void afterRender() {// Tell the Tapestry.Initializer to do the initializing of a Confirm,// which it will do when the DOM has been// fully loaded.JSONObject spec = new JSONObject();spec.put("elementId", clientElement.getClientId());spec.put("message", message);javaScriptSupport.addInitializerCall("confirm", spec);}
}

Index.java

支持索引模板的Java很简单,因为我们只需要定义一个数据源并提供一些动作处理程序即可。

package com.invariantproperties.sandbox.student.maintenance.web.pages.course;public class Index {@Property@Inject@Symbol(SymbolConstants.TAPESTRY_VERSION)private String tapestryVersion;@InjectComponentprivate Zone zone;@Injectprivate CourseFinderService courseFinderService;@Injectprivate CourseManagerService courseManagerService;@Propertyprivate Course course;// our sibling page@InjectPageprivate com.invariantproperties.sandbox.student.maintenance.web.pages.course.Editor editorPage;/*** Get the datasource containing our data.* * @return*/public GridDataSource getCourses() {return new CoursePagedDataSource(courseFinderService);}/*** Handle a delete request. This could fail, e.g., if the course has already* been deleted.* * @param courseUuid*/void onActionFromDelete(String courseUuid) {courseManagerService.deleteCourse(courseUuid, 0);}/*** Bring up editor page in create mode.* * @param courseUuid* @return*/Object onActionFromCreate() {editorPage.setup(Mode.CREATE, null);return editorPage;}/*** Bring up editor page in create mode.* * @param courseUuid* @return*/Object onActionFromCreate1() {return onActionFromCreate();}/*** Bring up editor page in review mode.* * @param courseUuid* @return*/Object onActionFromView(String courseUuid) {editorPage.setup(Mode.REVIEW, courseUuid);return editorPage;}/*** Bring up editor page in update mode.* * @param courseUuid* @return*/Object onActionFromUpdate(String courseUuid) {editorPage.setup(Mode.UPDATE, courseUuid);return editorPage;}
}

Editor.tml

CRUD页面可以是三个单独的页面(用于创建,查看和更新​​),也可以是一个页面。 我遵循的是Jumpstart网站使用的模式–一个页面。 老实说-我不确定他为什么做出这个决定-也许是因为页面紧密相关并且他使用事件处理? 无论如何,我将分别讨论这些元素。

创建模板

“创建”模板是一种简单的形式。 您可以看到HTML <input>元素得到了增强,它们具有一些特定于挂毯的属性,以及一些其他标记,例如<t:errors />和<t:submit>。

CustomFormCustomError是标准Tapestry FormError类的本地扩展。 它们目前为空,但允许我们轻松添加本地扩展。

<html t:type="layout" title="Course Editor"t:sidebarTitle="Framework Version"xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter"><t:zone t:id="zone">   <t:if test="modeCreate"><h1>Create</h1><form t:type="form" t:id="createForm" ><t:errors/><table><tr><th><t:label for="code"/>:</th><td><input t:type="TextField" t:id="code" value="course.code" t:validate="required, maxlength=12" size="12"/></td><td>(required)</td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="code"/></td></tr><tr><th><t:label for="name"/>:</th><td><input t:type="TextField" t:id="name" value="course.name" t:validate="required, maxlength=80" size="45"/></td><td>(required)</td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="name"/></td></tr><tr><th><t:label for="summary"/>:</th><td><input cols="50" rows="4" t:type="TextArea" t:id="summary" value="course.summary" t:validate="maxlength=400"/></td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="summary"/></td></tr><tr><th><t:label for="description"/>:</th><td><input cols="50" rows="12" t:type="TextArea" t:id="description" value="course.description" t:validate="maxlength=2000"/></td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="description"/></td></tr></table><div class="buttons"><t:submit t:event="cancelCreate" t:context="course.uuid" value="Cancel"/><input type="submit" value="Save"/></div></form></t:if>...
</html>

创建java

  • 相应的java类很简单。 我们必须定义一些自定义事件。
  • ActivationRequestParameter值是从URL查询字符串中提取的。
  • 课程字段包含创建新对象时要使用的值。
  • courseForm字段在模板上包含相应的<form>。
  • indexPage包含对索引页的引用。

有四个名为onEventFromCreateForm的事件处理程序,其中event
可以准备,验证,成功或失败。 每个事件处理程序都有非常特定的角色。

还有一个附加的事件处理程序onCancelCreate() 。 您可以在模板的<t:submit>标记中看到该事件的名称。

/*** This component will trigger the following events on its container (which in* this example is the page):* {@link Editor.web.components.examples.component.crud.Editor#CANCEL_CREATE} ,* {@link Editor.web.components.examples.component.crud.Editor#SUCCESSFUL_CREATE}* (Long courseUuid),* {@link Editor.web.components.examples.component.crud.Editor#FAILED_CREATE} ,*/
// @Events is applied to a component solely to document what events it may
// trigger. It is not checked at runtime.
@Events({ Editor.CANCEL_CREATE, Editor.SUCCESSFUL_CREATE, Editor.FAILED_CREATE })
public class Editor {public static final String CANCEL_CREATE = "cancelCreate";public static final String SUCCESSFUL_CREATE = "successfulCreate";public static final String FAILED_CREATE = "failedCreate";public enum Mode {CREATE, REVIEW, UPDATE;}// Parameters@ActivationRequestParameter@Propertyprivate Mode mode;@ActivationRequestParameter@Propertyprivate String courseUuid;// Screen fields@Propertyprivate Course course;// Work fields// This carries version through the redirect that follows a server-side// validation failure.@Persist(PersistenceConstants.FLASH)private Integer versionFlash;// Generally useful bits and pieces@Injectprivate CourseFinderService courseFinderService;@Injectprivate CourseManagerService courseManagerService;@Componentprivate CustomForm createForm;@Injectprivate ComponentResources componentResources;@InjectPageprivate com.invariantproperties.sandbox.student.maintenance.web.pages.course.Index indexPage;// The codepublic void setup(Mode mode, String courseUuid) {this.mode = mode;this.courseUuid = courseUuid;}// setupRender() is called by Tapestry right before it starts rendering the// component.void setupRender() {if (mode == Mode.REVIEW) {if (courseUuid == null) {course = null;// Handle null course in the template.} else {if (course == null) {try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {// Handle null course in the template.}}}}}// /// CREATE// /// Handle event "cancelCreate"Object onCancelCreate() {return indexPage;}// Component "createForm" bubbles up the PREPARE event when it is rendered// or submittedvoid onPrepareFromCreateForm() throws Exception {// Instantiate a Course for the form data to overlay.course = new Course();}// Component "createForm" bubbles up the VALIDATE event when it is submittedvoid onValidateFromCreateForm() {if (createForm.getHasErrors()) {// We get here only if a server-side validator detected an error.return;}try {course = courseManagerService.createCourse(course.getCode(), course.getName(), course.getSummary(),course.getDescription(), 1);} catch (RestClientFailureException e) {createForm.recordError("Internal error on server.");createForm.recordError(e.getMessage());} catch (Exception e) {createForm.recordError(ExceptionUtil.getRootCauseMessage(e));}}// Component "createForm" bubbles up SUCCESS or FAILURE when it is// submitted, depending on whether VALIDATE// records an errorboolean onSuccessFromCreateForm() {componentResources.triggerEvent(SUCCESSFUL_CREATE, new Object[] { course.getUuid() }, null);// We don't want "success" to bubble up, so we return true to say we've// handled it.mode = Mode.REVIEW;courseUuid = course.getUuid();return true;}boolean onFailureFromCreateForm() {// Rather than letting "failure" bubble up which doesn't say what you// were trying to do, we trigger new event// "failedCreate". It will bubble up because we don't have a handler// method for it.componentResources.triggerEvent(FAILED_CREATE, null, null);// We don't want "failure" to bubble up, so we return true to say we've// handled it.return true;}....
}

评论模板

“审阅”模板是一个简单的表。 它以表格形式包装,但仅用于页面底部的导航按钮。

<t:if test="modeReview"><h1>Review</h1><strong>Warning: no attempt is made to block XSS</strong><form t:type="form" t:id="reviewForm"><t:errors/><t:if test="course"><div t:type="if" t:test="deleteMessage" class="error">${deleteMessage}</div><table><tr><th>Uuid:</th><td>${course.uuid}</td></tr><tr><th>Code:</th><td>${course.code}</td></tr><tr><th>Name:</th><td>${course.name}</td></tr><tr><th>Summary:</th><td>${course.summary}</td></tr><tr><th>Description:</th><td>${course.description}</td></tr></table><div class="buttons"><t:submit t:event="toIndex" t:context="course.uuid" value="List"/><t:submit t:event="toUpdate" t:context="course.uuid" value="Update"/><t:submit t:event="delete" t:context="course.uuid" t:mixins="Confirm" t:message="Delete ${course.name}?" value="Delete"/></div></t:if><t:if negate="true" test="course">Course ${courseUuid} does not exist.<br/><br/></t:if></form></t:if>

回顾java

审阅表单所需的Java很简单-我们只需要加载数据即可。 我希望setupRender()足够,但实际上我需要onPrepareFromReviewForm()方法。

public class Editor {public enum Mode {CREATE, REVIEW, UPDATE;}// Parameters@ActivationRequestParameter@Propertyprivate Mode mode;@ActivationRequestParameter@Propertyprivate String courseUuid;// Screen fields@Propertyprivate Course course;// Generally useful bits and pieces@Injectprivate CourseFinderService courseFinderService;@Componentprivate CustomForm reviewForm;@Injectprivate ComponentResources componentResources;@InjectPageprivate com.invariantproperties.sandbox.student.maintenance.web.pages.course.Index indexPage;// The codepublic void setup(Mode mode, String courseUuid) {this.mode = mode;this.courseUuid = courseUuid;}// setupRender() is called by Tapestry right before it starts rendering the// component.void setupRender() {if (mode == Mode.REVIEW) {if (courseUuid == null) {course = null;// Handle null course in the template.} else {if (course == null) {try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {// Handle null course in the template.}}}}}// /// REVIEW// /void onPrepareFromReviewForm() {try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {// Handle null course in the template.}}// /// PAGE NAVIGATION// /// Handle event "toUpdate"boolean onToUpdate(String courseUuid) {mode = Mode.UPDATE;return false;}// Handle event "toIndex"Object onToIndex() {return indexPage;}....
}

UPDATE模板

最后,“更新”模板看起来类似于“创建”模板。

<t:if test="modeUpdate"><h1>Update</h1><strong>Warning: no attempt is made to block XSS</strong><form t:type="form" t:id="updateForm"><t:errors/><t:if test="course"><!-- If optimistic locking is not needed then comment out this next line. It works because Hidden fields are part of the submit. --><!-- <t:hidden value="course.version"/> --><table><tr><th><t:label for="updCode"/>:</th><td><input t:type="TextField" t:id="updCode" value="course.code" t:disabled="true" size="12"/></td><td>(read-only)</td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="updName"/></td></tr><tr><th><t:label for="updName"/>:</th><td><input t:type="TextField" t:id="updName" value="course.name" t:validate="required, maxlength=80" size="45"/></td><td>(required)</td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="updSummary"/></td></tr><tr><th><t:label for="updSummary"/>:</th><td><input cols="50" rows="4" t:type="TextArea" t:id="updSummary" value="course.summary" t:validate="maxlength=400"/></td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="updSummary"/></td></tr><tr><th><t:label for="updDescription"/>:</th><td><input cols="50" rows="12" t:type="TextArea" t:id="updDescription" value="course.description" t:validate="maxlength=50"/></td></tr><tr class="err"><th></th><td colspan="2"><t:CustomError for="updDescription"/></td></tr></table><div class="buttons"><t:submit t:event="toIndex" t:context="course.uuid" value="List"/><t:submit t:event="cancelUpdate" t:context="course.uuid" value="Cancel"/><input t:type="submit" value="Save"/></div></t:if><t:if negate="true" test="course">Course ${courseUuid} does not exist.<br/><br/></t:if></form>    </t:if>

更新java

同样,“更新” Java代码看起来很像“创建” Java代码。 最大的区别是,我们必须能够处理在尝试更新数据库之前已删除课程的比赛条件。

@Events({ Editor.TO_UPDATE, Editor.CANCEL_UPDATE,Editor.SUCCESSFUL_UPDATE, Editor.FAILED_UPDATE })
public class Editor {public static final String TO_UPDATE = "toUpdate";public static final String CANCEL_UPDATE = "cancelUpdate";public static final String SUCCESSFUL_UPDATE = "successfulUpdate";public static final String FAILED_UPDATE = "failedUpdate";public enum Mode {CREATE, REVIEW, UPDATE;}// Parameters@ActivationRequestParameter@Propertyprivate Mode mode;@ActivationRequestParameter@Propertyprivate String courseUuid;// Screen fields@Propertyprivate Course course;@Property@Persist(PersistenceConstants.FLASH)private String deleteMessage;// Work fields// This carries version through the redirect that follows a server-side// validation failure.@Persist(PersistenceConstants.FLASH)private Integer versionFlash;// Generally useful bits and pieces@Injectprivate CourseFinderService courseFinderService;@Injectprivate CourseManagerService courseManagerService;@Componentprivate CustomForm updateForm;@Injectprivate ComponentResources componentResources;@InjectPageprivate com.invariantproperties.sandbox.student.maintenance.web.pages.course.Index indexPage;// The codepublic void setup(Mode mode, String courseUuid) {this.mode = mode;this.courseUuid = courseUuid;}// setupRender() is called by Tapestry right before it starts rendering the// component.void setupRender() {if (mode == Mode.REVIEW) {if (courseUuid == null) {course = null;// Handle null course in the template.} else {if (course == null) {try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {// Handle null course in the template.}}}}}// /// UPDATE// /// Handle event "cancelUpdate"Object onCancelUpdate(String courseUuid) {return indexPage;}// Component "updateForm" bubbles up the PREPARE_FOR_RENDER event during// form rendervoid onPrepareForRenderFromUpdateForm() {try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {// Handle null course in the template.}// If the form has errors then we're redisplaying after a redirect.// Form will restore your input values but it's up to us to restore// Hidden values.if (updateForm.getHasErrors()) {if (course != null) {course.setVersion(versionFlash);}}}// Component "updateForm" bubbles up the PREPARE_FOR_SUBMIT event during for// submissionvoid onPrepareForSubmitFromUpdateForm() {// Get objects for the form fields to overlay.try {course = courseFinderService.findCourseByUuid(courseUuid);} catch (ObjectNotFoundException e) {course = new Course();updateForm.recordError("Course has been deleted by another process.");}}// Component "updateForm" bubbles up the VALIDATE event when it is submittedvoid onValidateFromUpdateForm() {if (updateForm.getHasErrors()) {// We get here only if a server-side validator detected an error.return;}try {courseManagerService.updateCourse(course, course.getName(), course.getSummary(), course.getDescription(), 1);} catch (RestClientFailureException e) {updateForm.recordError("Internal error on server.");updateForm.recordError(e.getMessage());} catch (Exception e) {// Display the cause. In a real system we would try harder to get a// user-friendly message.updateForm.recordError(ExceptionUtil.getRootCauseMessage(e));}}// Component "updateForm" bubbles up SUCCESS or FAILURE when it is// submitted, depending on whether VALIDATE// records an errorboolean onSuccessFromUpdateForm() {// We want to tell our containing page explicitly what course we've// updated, so we trigger new event// "successfulUpdate" with a parameter. It will bubble up because we// don't have a handler method for it.componentResources.triggerEvent(SUCCESSFUL_UPDATE, new Object[] { courseUuid }, null);// We don't want "success" to bubble up, so we return true to say we've// handled it.mode = Mode.REVIEW;return true;}boolean onFailureFromUpdateForm() {versionFlash = course.getVersion();// Rather than letting "failure" bubble up which doesn't say what you// were trying to do, we trigger new event// "failedUpdate". It will bubble up because we don't have a handler// method for it.componentResources.triggerEvent(FAILED_UPDATE, new Object[] { courseUuid }, null);// We don't want "failure" to bubble up, so we return true to say we've// handled it.return true;}
}

删除模板和Java

编辑器没有显式的“删除”模式,但确实支持删除审阅和更新页面上的当前对象。

// /// DELETE// /// Handle event "delete"Object onDelete(String courseUuid) {this.courseUuid = courseUuid;int courseVersion = 0;try {courseManagerService.deleteCourse(courseUuid, courseVersion);} catch (ObjectNotFoundException e) {// the object's already deleted} catch (RestClientFailureException e) {createForm.recordError("Internal error on server.");createForm.recordError(e.getMessage());// Display the cause. In a real system we would try harder to get a// user-friendly message.deleteMessage = ExceptionUtil.getRootCauseMessage(e);// Trigger new event "failedDelete" which will bubble up.componentResources.triggerEvent(FAILED_DELETE, new Object[] { courseUuid }, null);// We don't want "delete" to bubble up, so we return true to say// we've handled it.return true;} catch (Exception e) {// Display the cause. In a real system we would try harder to get a// user-friendly message.deleteMessage = ExceptionUtil.getRootCauseMessage(e);// Trigger new event "failedDelete" which will bubble up.componentResources.triggerEvent(FAILED_DELETE, new Object[] { courseUuid }, null);// We don't want "delete" to bubble up, so we return true to say// we've handled it.return true;}// Trigger new event "successfulDelete" which will bubble up.componentResources.triggerEvent(SUCCESFUL_DELETE, new Object[] { courseUuid }, null);// We don't want "delete" to bubble up, so we return true to say we've// handled it.return indexPage;}

下一步

显而易见的下一步是改进错误消息,增加对分页,支持以及一对多和多对多关系的支持。 所有这些都需要修改REST负载。 我在管道中还有一些其他项目,例如ExceptionService,更不用说安全问题了。

源代码

  • 可从http://code.google.com/p/invariant-properties-blog/source/browse/student获取源代码。

参考: 项目学生: Invariant Properties博客上来自JCG合作伙伴 Bear Giles的Maintenance Webapp(可编辑) 。

翻译自: https://www.javacodegeeks.com/2014/02/project-student-maintenance-webapp-editable.html

webapp文本编辑器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

交换机的端口结构及端口类型

交换机在同一时刻可进行多个端口对之间的数据传输。每一端口都可视为独立的物理网段&#xff08;注&#xff1a;非IP网段&#xff09;&#xff0c;连接在其上的网络设备独自享有全部的带宽&#xff0c;无须同其他设备竞争使用。那么&#xff0c;你对于交换机的端口结构及端口类…

前9个免费的Java进程监视工具以及如何选择一种

这样就可以运行Java代码了。 也许它甚至可以在生产服务器上运行。 在您完成出色工作之后&#xff0c;我们得到了好消息和令人讨厌的消息。 令人讨厌的消息是&#xff0c;现在开始调试。 就是调试和应用程序性能监视。 这意味着您不仅需要查看编写的代码&#xff0c;还可以查看…

redisson的锁的类型_厉害了,中间件Redisson原来这么好用!

点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]作者&#xff1a;bravoban原文&#xff1a;http://tech.lede.com/2017/03/08/rd/server/Redisson/针对项目中使用的分布式锁进行简单的示例配置以及源码解析&#xff0c;并列举源码中使用到的一些基础知识点&#xff0c;但…

探探自动配对PHP_CentOS7 - 安装Apache HTTP Server和PHP

安装Apache HTTP Server和PHP你可能听说过LAMP的缩写&#xff0c;它代表Linux&#xff0c;Apache&#xff0c;MySQL和PHP。 它指的是用于提供网站和Web应用程序的流行技术配对。 本文教您如何安装Apache HTTP Server(简称Apache)并将其配置为与PHP一起使用以提供动态Web内容.Ap…

网管型交换机比普通交换机有哪些明显优势

现在网络这么普及&#xff0c;对于交换机的需求也就越发的重要了&#xff0c;而市面上交换机的型号这么多&#xff0c;之前我们也分析过按照不同的情况怎么区分交换机&#xff0c;但浏览名称的时候我们也会发现&#xff0c;许多交换机的简介都会写着网管型交换机和非网管型交换…

cryptojs支持rsa加密_新特性解读 | 从 wireshark 看 MySQL 8.0 加密连接

作者&#xff1a;秦福朗爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。热爱 IT&#xff0c;喜欢在互联网里畅游&#xff0c;擅长摄影、厨艺&#xff0c;不会厨艺的 DBA 不是好司机&#xff0c;didi~本文来源&#xff1a;原创投稿*爱可生开源社区出品…

sap-erp实施心得_实施动态代理-比较

sap-erp实施心得有时需要拦截某些方法调用&#xff0c;以便每次调用被拦截方法时都执行自己的逻辑。 如果您不属于Java EE的CDI领域&#xff0c;并且不想使用诸如Aspectj之类的AOP框架&#xff0c;那么您将有一个简单而有效的替代方法。 从1.5版开始&#xff0c;JDK附带了类ja…

保存点云数据_PCL入门系列三——PCL进行数据读写

本节课我们将了解到以下内容&#xff1a;基本的PCL中的数据类型&#xff1b;使用PCL进行简单编程&#xff1a;写文件与读文件。一、PCL库基本数据类型上一节课&#xff0c;我们使用PCL库在本地写入了一个名为test_pcd.pcd的文件。我们划分一下程序的任务步骤&#xff1a;构造pc…

win8系统的计算机共享在哪里设置方法,win10系统设置与win8系统局域网文件共享的方案...

win10系统使用久了&#xff0c;好多网友反馈说关于对win10系统设置与win8.1系统局域网文件共享设置的方法&#xff0c;在使用win10系统的过程中经常不知道如何去对win10系统设置与win8.1系统局域网文件共享进行设置&#xff0c;有什么好的办法去设置win10系统设置与win8.1系统局…

光端机的使用方法

光端机是一种不仅可以传输视频信号&#xff0c;还能传输音频、电话、网络、和很多种控制信号的以太网介质传输设备&#xff0c;目前主要使用安防监控行业。那么&#xff0c;光端机是怎么使用的&#xff0c;接下来就由飞畅科技的小编来为大家详细介绍下光端机的使用方法吧&#…

用香港服务器建收费网站,使用香港站群服务器搭建网站的好处有哪些?

香港站群服务器搭建网站的作用&#xff1a;1、香港站群服务器有利于提高网站被搜索引擎收录情况;2、搭建站群能够有效降低网站被封的风险;3、当网站遭受攻击时&#xff0c;可快速通过带有独立IP的网站来查出问题所在&#xff0c;从而有效提高服务器的维护。香港站群服务器搭建站…

分数化简_分数应用题七讲 (一) 图示法解分数应用题

一、今日一讲图示法就是用线段图(或其它图形)把题目中的已知条件和问题表示出来&#xff0c;这样可以把抽象的数量关系具体化&#xff0c;往往可以从图中找到解题的突破口。运用图示法教学应用题&#xff0c;是培养思维能力的有效方法之一。图示法不仅可以形象地、直观地反映分…

发送广播_DHCP服务器什么时候发送?为什么request要广播发送?那还不看?

动态主机配置协议&#xff1a;DHCP 用来集中管理、分配IP地址&#xff0c;使网络环境中的主机能够动态获取IP地址、网关地址、DNS服务器地址等信息&#xff1b;DHCP采用客户端服务器模式&#xff0c;端口号&#xff1a;客户端为68(中继模式下67)&#xff0c;服务器端为67版本一…

开关量光端机指示灯说明及常见故障问题处理方法

开关量光端机可以使开关量信号通过光缆在光纤上传输双向控制。全数字光传输通道&#xff0c;确保高质量的信号传输。面板上有电源指示灯、光信号指示灯数据信号指示灯&#xff0c;可以直观的检测电源、光信号、数据信号状态。单向系列开关量光端机是高性能&#xff0c;高可靠性…

为特使建立控制平面的指南-部署权衡

部署控制平面组件 构建并设计了控制平面后&#xff0c;您将需要确切确定如何部署其组件。 在这里&#xff0c;您可以选择将控制平面与数据平面共置一处以集中控制平面。 这里还有一个中间立场&#xff1a;部署与控制平面位于同一位置的某些组件&#xff0c;并使某些组件保持集中…

大牛服务器超时位置模拟失败,大牛模拟定位掉线怎么办 | 手游网游页游攻略大全...

发布时间&#xff1a;2016-07-07在第四期"微分享"活动中,有许多游戏大牛向小智讲述了关于玩游戏的妙招.巧招和绝招,现小智将这些内容推送给大家! 1.如何在3v3中取得好名次?(由"天才的小白"玩家供稿) 打3v3 ...标签&#xff1a;游乐网 游戏攻略发布时间&am…

宋佳乐博客全站正版PHP源码下载丨自助建站源码丨音乐外链源码丨最新图床源码丨官方网站源码丨网页跳转源码丨云相册源码丨打包下载

本套源码共包含了六套网站系统&#xff0c;请在下方看演示站&#xff1a; 一&#xff1a;主页跳转演示地址&#xff1a;http://ssl.songjiale.com&#xff08;无演示图&#xff09; 二&#xff1a;官方网站演示地址&#xff1a;http://ssl.songjiale.com/upload &#xff08;…

css3怎么排除第一个,css怎么排除第一个子元素

css排除第一个子元素的方法&#xff1a;1、通过使用伪类选择器“:not”实现排除&#xff1b;2、通过使用“nth-of-type”或者“nth-child”实现排除&#xff1b;3、通过使用“”或者“~”兄弟选择符实现获取排除第一个之外的子元素。本文操作环境&#xff1a;windows7系统、HTM…

如何解决光端机的开关量问题?

光端机开关量问题可以说是光端机的常见问题之一&#xff0c;对监控效果有比较大的影响&#xff0c;那么&#xff0c;我们应该如何解决光端机的开关量问题呢&#xff1f;接下来就由杭州飞畅科技的小编来为大家详细讲解下吧&#xff0c;感兴趣的朋友就一起来了解下&#xff01; …

什么是电视光端机?电视光端机是怎么分类的?

现如今&#xff0c;随着国内通信网络的发展&#xff0c;电视光端机应用的监控范围也越来越广。在高速公路、银行、电力、电信等的监控领域都要求对视频信号进行远程的传输&#xff0c;目前主要的解决方法是利用光端机将视频信号转化为数字信号通过光纤进行传输。那么&#xff0…