jpa jsf_完整Web应用程序Tomcat JSF Primefaces JPA Hibernate –第2部分

jpa jsf

托管豆

这篇文章是本教程第1部分的继续。

在“ com.mb”包中,您将需要创建以下类:

package com.mb;import org.primefaces.context.RequestContext;import com.util.JSFMessageUtil;public class AbstractMB {private static final String KEEP_DIALOG_OPENED = 'KEEP_DIALOG_OPENED';public AbstractMB() {super();}protected void displayErrorMessageToUser(String message) {JSFMessageUtil messageUtil = new JSFMessageUtil();messageUtil.sendErrorMessageToUser(message);}protected void displayInfoMessageToUser(String message) {JSFMessageUtil messageUtil = new JSFMessageUtil();messageUtil.sendInfoMessageToUser(message);}protected void closeDialog(){getRequestContext().addCallbackParam(KEEP_DIALOG_OPENED, false);}protected void keepDialogOpen(){getRequestContext().addCallbackParam(KEEP_DIALOG_OPENED, true);}protected RequestContext getRequestContext(){return RequestContext.getCurrentInstance();}
}
package com.mb;import java.io.Serializable;
import java.util.List;import javax.faces.bean.*;import com.facade.DogFacade;
import com.model.Dog;@ViewScoped
@ManagedBean
public class DogMB extends AbstractMB implements Serializable {private static final long serialVersionUID = 1L;private Dog dog;private List<Dog> dogs;private DogFacade dogFacade;public DogFacade getDogFacade() {if (dogFacade == null) {dogFacade = new DogFacade();}return dogFacade;}public Dog getDog() {if (dog == null) {dog = new Dog();}return dog;}public void setDog(Dog dog) {this.dog = dog;}public void createDog() {try {getDogFacade().createDog(dog);closeDialog();displayInfoMessageToUser('Created With Sucess');loadDogs();resetDog();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void updateDog() {try {getDogFacade().updateDog(dog);closeDialog();displayInfoMessageToUser('Updated With Sucess');loadDogs();resetDog();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void deleteDog() {try {getDogFacade().deleteDog(dog);closeDialog();displayInfoMessageToUser('Deleted With Sucess');loadDogs();resetDog();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public List<Dog> getAllDogs() {if (dogs == null) {loadDogs();}return dogs;}private void loadDogs() {dogs = getDogFacade().listAll();}public void resetDog() {dog = new Dog();}
}
package com.mb;import java.io.Serializable;import javax.faces.bean.*;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;import com.model.User;@SessionScoped
@ManagedBean(name='userMB')
public class UserMB implements Serializable {public static final String INJECTION_NAME = '#{userMB}';private static final long serialVersionUID = 1L;private User user;public boolean isAdmin() {return user.isAdmin();}public boolean isDefaultUser() {return user.isUser();}public String logOut() {getRequest().getSession().invalidate();return '/pages/public/login.xhtml';}private HttpServletRequest getRequest() {return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();}public User getUser() {return user;}public void setUser(User user) {this.user = user;}
}
package com.mb;import java.io.Serializable;
import java.util.*;import javax.faces.bean.*;import com.facade.*;
import com.model.*;
import com.sun.faces.context.flash.ELFlash;@ViewScoped
@ManagedBean
public class PersonMB extends AbstractMB implements Serializable {private static final long serialVersionUID = 1L;private static final String SELECTED_PERSON = 'selectedPerson';private Dog dog;private Person person;private Person personWithDogs;private Person personWithDogsForDetail;private List<Dog> allDogs;private List<Person> persons;private DogFacade dogFacade;private PersonFacade personFacade;public void createPerson() {try {getPersonFacade().createPerson(person);closeDialog();displayInfoMessageToUser('Created With Sucess');loadPersons();resetPerson();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void updatePerson() {try {getPersonFacade().updatePerson(person);closeDialog();displayInfoMessageToUser('Updated With Sucess');loadPersons();resetPerson();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void deletePerson() {try {getPersonFacade().deletePerson(person);closeDialog();displayInfoMessageToUser('Deleted With Sucess');loadPersons();resetPerson();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void addDogToPerson() {try {getPersonFacade().addDogToPerson(dog.getId(), personWithDogs.getId());closeDialog();displayInfoMessageToUser('Added With Sucess');reloadPersonWithDogs();resetDog();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public void removeDogFromPerson() {try {getPersonFacade().removeDogFromPerson(dog.getId(), personWithDogs.getId());closeDialog();displayInfoMessageToUser('Removed With Sucess');reloadPersonWithDogs();resetDog();} catch (Exception e) {keepDialogOpen();displayErrorMessageToUser('Ops, we could not create. Try again later');e.printStackTrace();}}public Person getPersonWithDogs() {if (personWithDogs == null) {if (person == null) {person = (Person) ELFlash.getFlash().get(SELECTED_PERSON);}personWithDogs = getPersonFacade().findPersonWithAllDogs(person.getId());}return personWithDogs;}public void setPersonWithDogsForDetail(Person person) {personWithDogsForDetail = getPersonFacade().findPersonWithAllDogs(person.getId());}public Person getPersonWithDogsForDetail() {if (personWithDogsForDetail == null) {personWithDogsForDetail = new Person();personWithDogsForDetail.setDogs(new ArrayList<Dog>());}return personWithDogsForDetail;}public void resetPersonWithDogsForDetail(){personWithDogsForDetail = new Person();}public String editPersonDogs() {ELFlash.getFlash().put(SELECTED_PERSON, person);return '/pages/protected/defaultUser/personDogs/personDogs.xhtml';}public List<Dog> complete(String name) {List<Dog> queryResult = new ArrayList<Dog>();if (allDogs == null) {dogFacade = new DogFacade();allDogs = dogFacade.listAll();}allDogs.removeAll(personWithDogs.getDogs());for (Dog dog : allDogs) {if (dog.getName().toLowerCase().contains(name.toLowerCase())) {queryResult.add(dog);}}return queryResult;}public PersonFacade getPersonFacade() {if (personFacade == null) {personFacade = new PersonFacade();}return personFacade;}public Person getPerson() {if (person == null) {person = new Person();}return person;}public void setPerson(Person person) {this.person = person;}public List<Person> getAllPersons() {if (persons == null) {loadPersons();}return persons;}private void loadPersons() {persons = getPersonFacade().listAll();}public void resetPerson() {person = new Person();}public Dog getDog() {if (dog == null) {dog = new Dog();}return dog;}public void setDog(Dog dog) {this.dog = dog;}public void resetDog() {dog = new Dog();}private void reloadPersonWithDogs() {personWithDogs = getPersonFacade().findPersonWithAllDogs(person.getId());}
}
package com.mb;import javax.faces.bean.*;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;import com.facade.UserFacade;
import com.model.User;@RequestScoped
@ManagedBean
public class LoginMB extends AbstractMB {@ManagedProperty(value = UserMB.INJECTION_NAME)private UserMB userMB;private String email;private String password;public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String login() {UserFacade userFacade = new UserFacade();User user = userFacade.isValidLogin(email, password);if(user != null){userMB.setUser(user);FacesContext context = FacesContext.getCurrentInstance();HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();request.getSession().setAttribute('user', user);return '/pages/protected/index.xhtml';}displayErrorMessageToUser('Check your email/password');return null;}public void setUserMB(UserMB userMB) {this.userMB = userMB;} 
}

关于上面的代码:

  • 所有ManagedBeans仅负责VIEW操作; ManagedBeans应该负责处理业务方法的唯一结果。 ManagedBeans中没有业务规则。 在视图层中执行一些业务操作非常容易,但这不是一个好习惯。
  • LoginMB类使用另一个ManagedBean(UserMB),并在其中注入了它。 要将一个ManagedBean注入另一个ManagedBean中,您必须执行以下操作:
    • 在注入的ManagedBean的顶部使用@ManagedProperty
  • PersonMB类可能会因为其太大而接受重构操作。 这样的PersonMB可以使新手开发人员更轻松地理解代码。

关于@ViewScoped的观察

您将在带有@ViewScoped批注的托管bean中看到一些重新加载和重置方法。 这两种方法都需要重置对象状态。 例如,狗对象将在方法执行后保存视图中的值(持久保存在数据库中,在对话框中显示值)。 如果用户打开创建对话框并成功创建狗,则该狗对象将在用户停留在同一页面时保留所有值。 如果用户再次打开创建对话框,则将在此处显示最后记录的狗的所有数据。 这就是为什么我们有重置方法的原因。

如果更新数据库中的对象,则用户视图中的对象也必须接收此更新,ManagedBean对象也必须接收此新数据。 如果您在数据库中更新了狗名,则狗列表也应收到此更新的狗。 您可以在数据库中查询此新数据,也可以仅更新托管Bean值。

开发人员必须注意:

  • 重新加载查询数据库的托管Bean数据(重新加载方法) :如果重新加载ManagedBean对象的激发查询附带大量数据,则其查询可能会影响应用程序性能。 开发人员可以使用具有延迟加载的数据表。 单击此处查看有关Lazy Datatable的更多信息 。
  • 在不查询数据库的情况下,直接在托管Bean中重新加载更新的对象 :假设user1更新了数据库中的dog1名称,同时user2更新了dog2年龄。 如果user1更新dog2,则user1将看到有关dog2的旧数据,这可能会导致数据库完整性问题。 该方法的解决方案可以是数据库表中的版本字段。 在更新发生之前,将检查此字段。 如果版本字段不具有数据库中找到的相同值,则可能引发异常。 使用此方法,如果user1更新dog2,则版本值将不同。

JSFMessageUtil

在“ com.util”包中,创建以下类:

package com.util;import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;public class JSFMessageUtil {public void sendInfoMessageToUser(String message) {FacesMessage facesMessage = createMessage(FacesMessage.SEVERITY_INFO, message);addMessageToJsfContext(facesMessage);}public void sendErrorMessageToUser(String message) {FacesMessage facesMessage = createMessage(FacesMessage.SEVERITY_WARN, message);addMessageToJsfContext(facesMessage);}private FacesMessage createMessage(Severity severity, String mensagemErro) {return new FacesMessage(severity, mensagemErro, mensagemErro);}private void addMessageToJsfContext(FacesMessage facesMessage) {FacesContext.getCurrentInstance().addMessage(null, facesMessage);}
}

此类将处理将显示给用户的所有JSF消息。 此类将帮助我们的ManagedBeans失去类之间的耦合。

创建一个类来处理对话框动作也是一个好主意。

配置文件

在源“ src”文件夹中,创建以下文件:

log4.properties

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n# Root logger option
log4j.rootLogger=ERROR, stdout# Hibernate logging options (INFO only shows startup messages)
log4j.logger.org.hibernate=ERROR# Log JDBC bind parameter runtime arguments
#log4j.logger.org.hibernate.type=TRACE

messages.properties

#Actions
welcomeMessage=Hello! Show me the best soccer team logo ever
update=Update
create=Create
delete=Delete
cancel=Cancel
detail=Detail
logIn=Log In
add=Add
remove=Remove
ok=Ok
logOut= Log Out
javax.faces.component.UIInput.REQUIRED={0}: is empty. Please, provide some value
javax.faces.validator.LengthValidator.MINIMUM={1}: Length is less than allowable minimum of u2018u2019{0}u2019u2019
noRecords=No data to display
deleteRecord=Do you want do delete the record#Login / Roles Validations
loginHello=Login to access secure pages
loginUserName=Username
loginPassword=Password
logout=Log Out
loginWelcomeMessage=Welcome
accessDeniedHeader=Wow, our ninja cat found you!
accessDeniedText=Sorry but you can not access that page. If you try again, that ninja cat gonna kick you harder! >= )
accessDeniedButton=You got-me, take me out. =/#Person
person=Person
personPlural=Persons
personName=Name
personAge=Age
personDogs=These dogs belongs to
personAddDogTo=Add the selected Dog To
personRemoveDogFrom=Remove the selected Dog from
personEditDogs=Edit Dogs#Dog
dog=Dog
dogPlural=Dogs
dogName=Name
dogAge=Age

看一下“ lo4j.properties ”,注释#log4j.logger.org.hibernate.type = TRACE行。 如果要查看由Hibernate创建的查询,则需要将文件的其他配置从ERROR编辑为DEBUG,并从上面的行中删除#。

您将能够看到Hibernate执行的查询及其参数。

xhtml页面,面

在WebContent文件夹中,您将找到以下文件:

让我们看看如何将Facelets应用于项目。 在“ / WebContent / pages / protected / templates /”文件夹下创建以下文件:

left.xhtml

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns='http://www.w3.org/1999/xhtml'xmlns:ui='http://java.sun.com/jsf/facelets'xmlns:h='http://java.sun.com/jsf/html'xmlns:p='http://primefaces.org/ui'><h:body><ui:composition><h:form><p:commandButton styleClass='menuButton' icon='ui-icon-arrowstop-1-e' rendered='#{userMB.admin or userMB.defaultUser}' action='/pages/protected/defaultUser/defaultUserIndex.xhtml' value='#{bundle.personPlural}' ajax='false' immediate='true' /><br /><p:commandButton styleClass='menuButton' icon='ui-icon-arrowstop-1-e' rendered='#{userMB.admin}' action='/pages/protected/admin/adminIndex.xhtml' value='#{bundle.dogPlural}' ajax='false' immediate='true' /><br /></h:form></ui:composition>
</h:body>
</html>

master.xhtml

<?xml version='1.0' encoding='UTF-8' ?>  
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns='http://www.w3.org/1999/xhtml'xmlns:ui='http://java.sun.com/jsf/facelets'xmlns:h='http://java.sun.com/jsf/html'xmlns:p='http://primefaces.org/ui'xmlns:f='http://java.sun.com/jsf/core'><h:head><title>CrudJSF</title><h:outputStylesheet library='css' name='main.css' /><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
</h:head><h:body><f:view contentType='text/html; charset=UTF-8' encoding='UTF-8' ><div id='divTop' style='vertical-align: middle;'><ui:insert name='divTop'><ui:include src='top.xhtml' /></ui:insert></div><div id='divLeft'><ui:insert name='divLeft'><ui:include src='left.xhtml' /></ui:insert></div><div id='divMain'><p:growl id='messageGrowl' /><ui:insert name='divMain' /></div><h:outputScript library='javascript' name='jscodes.js' /></f:view>
</h:body>
</html>

“ top.xhtml”

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns='http://www.w3.org/1999/xhtml'xmlns:ui='http://java.sun.com/jsf/facelets'xmlns:h='http://java.sun.com/jsf/html'xmlns:p='http://primefaces.org/ui'><h:body>   <ui:composition><div id='topMessage'><h1><h:form>#{bundle.loginWelcomeMessage}: #{userMB.user.name} | <p:commandButton value='#{bundle.logOut}' action='#{userMB.logOut()}' ajax='false' style='font-size: 20px;' /></h:form></h1></div></ui:composition>   </h:body>
</html>

上面的代码将成为该应用程序所有xhtml页面的基础。 应用Facelets模式以重用xhtml代码非常重要。 在下面,您可以在xhtml页面中看到如何应用Facelets,请注意,开发人员只需要覆盖所需的部分:

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml' xmlns:ui='http://java.sun.com/jsf/facelets' xmlns:h='http://java.sun.com/jsf/html'xmlns:f='http://java.sun.com/jsf/core' xmlns:p='http://primefaces.org/ui' >
<h:body><ui:composition template='/pages/protected/templates/master.xhtml'><ui:define name='divMain'>#{bundle.welcomeMessage} :<br/><h:graphicImage library='images' name='logoReal.png' /></ui:define> </ui:composition>
</h:body>
</html>

请注意,只有“ divMain ”被覆盖,其他部分保持不变。 这是Facelets的最大优势,您无需在每个页面中使用网站的所有区域。

继续第三部分 。

参考:在uaiHebert博客上,来自我们的JCG合作伙伴 Hebert Coelho的Tomcat JSF Primefaces JPA Hibernate完整Web应用程序 。

翻译自: https://www.javacodegeeks.com/2012/07/full-web-application-tomcat-jsf_04.html

jpa jsf

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

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

相关文章

【利好工具】JavaScript及时运行调试工具

今天要介绍的这个工具叫RunJS[1]&#xff0c;是运行在各大系统上的客户端&#xff0c;目前支持主流的macOS、Windows、Debian和Universal Linux平台。你可以在上面编写你的JavaScript或TypeScript代码&#xff0c;并且获得即时反馈。它的左边是代码区域&#xff0c;右边是输出结…

CIFAR-10 dataset 的下载与使用

基本信息 CIFAR-10 是一个包含60000张图片的数据集。其中每张照片为32*32的彩色照片&#xff0c;每个像素点包括RGB三个数值&#xff0c;数值范围 0 ~ 255。 所有照片分属10个不同的类别&#xff0c;分别是 airplane, automobile, bird, cat, deer, dog, frog, horse, ship, tr…

教你如何创建一款属于自己的VSCode主题

你有没有想过创建一款属于自己的VSCode主题&#xff1f;没有你想像的那么难&#xff0c;但是真正实现起来也不是那么轻松&#xff0c;需要你对将要去改变的主题的一些属性要有所了解和准备。如果你要想让你的主题适用于多种编程语言&#xff0c;并且看起来还很漂亮的话&#xf…

调试

http://www.cnblogs.com/CARPE-DIEM-wu/p/7798119.html 黄金规则 从帮助台得到的观点是不明确的 检查插头 不要想,而要看 回到目录制造失败 回到目录不要想,而要看 回到目录分而治之 回到目录一次只改一个地方 回到目录保持审计跟踪 回到目录检查插头 回到目录获得全新观点 回到…

【视频内含福利】原来手机套壳视频是这么做出来的

最近视频圈子里都在发这种视频&#xff0c;究竟是怎么做出来的&#xff1f;研究下来发现原来是用的这款名字叫Record Maker的APP&#xff0c;旨在帮助用户轻松快速给视频加上手机壳的效果。目前App Store上的版本是1.2.1&#xff0c;最近一次更新支持了iPhone11/iPhone12模型&a…

apache thrift_使用Java快速入门的Apache Thrift

apache thriftApache Thrift是由facebook创建的RPC框架&#xff0c;现在它是一个Apache项目。 Thrift允许您在不依赖语言的定义文件中定义数据类型和服务接口。 该定义文件用作编译器的输入&#xff0c;以生成用于构建通过不同编程语言进行通信的RPC客户端和服务器的代码。 您也…

前端八大灵感设计,代码变为现实

我们都知道掌握编程技术是一项很难的事情&#xff0c;没有捷径可走。需要我们在日复一日的工作中去锻炼。如果想要达到擅长甚至需要长年累月的积累。下面列举了一些可以给你带来编码灵感的例子&#xff0c;相信你看到会有想去写代码的冲动。因为一个好的工程师&#xff0c;是不…

Apple 公司开发者账号添加团队成员

Apple 公司开发者账号添加团队成员 简介 首先公司内部团队开发需要的账号类型为公司账号&#xff0c;可以添加团队成员协同开发。 账号下的团队成员有三种角色&#xff1a; Team Agent (代理) 代理: 就是注册开发者账号的那一个&#xff0c;权限最高&#xff0c;续费和创建开发…

八个使前端工程师惊艳的效果设计,码否?

我们都知道掌握编程技术是一项很难的事情&#xff0c;没有捷径可走。需要我们在日复一日的工作中去锻炼。如果想要达到擅长甚至需要长年累月的积累。 下面列举了一些可以给你带来编码灵感的例子&#xff0c;相信你看到会有想去写代码的冲动。 因为一个好的工程师&#xff0c;…

OpenStack_I版 1.准备过程

openstack是一个开源云平台&#xff0c;python开发此次部署为实验环境&#xff0c; 采用扁平化简单的网络架构部署  优点&#xff1a;低耦合的&#xff0c;模块化Nova 计算资源池Glance 镜像服务Swift 对象存储Horizon 对计算资源&#xff0c;网络资源起别…

快点,再快点!

现在看视频不来个两倍速&#xff08;或者更快&#xff09;都觉得在浪费生命。特别是在看视频教程的时候&#xff0c;文字我们可以做到一目十行&#xff0c;但是视频呢&#xff0c;如果有字幕&#xff0c;我们甚至不用听清&#xff0c;用3倍速或者4倍速完全没有问题&#xff0c;…

jetty eclipse_3个步骤实现Jetty和Eclipse集成

jetty eclipse本教程将引导您逐步了解如何集成Jetty和Eclipse&#xff0c;以及如何在Eclipse中的Jetty服务器上运行Web应用程序。 脚步&#xff1a; 安装Jetty Eclipse插件 建立网路应用程式 运行网络应用 1 –安装Jetty Eclipse插件 将服务器添加到“服务器”视图时&…

使用React和Tailwind CSS搭建项目模板

公众号关注 “太空编程”设为 “星标”&#xff0c;带你了解硬核的编程知识&#xff01;众所周知&#xff0c;Tailwind CSS框架越来越流行&#xff0c;所以我决定尝试学习并使用Tailwind CSS来搭建一个项目模板&#xff0c;一方面自己深入学习下&#xff0c;二来帮助新人更快地…

PHP实现前台页面与MySQL的数据绑定、同步更新

今天我来给大家介绍一个PHP-MySQL的小项目。 使用 PHP和前台Ajax 实现在前台对MySQL数据库中数据的增、删等操作语句功能。 如果有问题&#xff0c;欢迎拍砖~ 有不懂的地方&#xff0c;提出来咱们一起探讨~ 首先&#xff0c;我们先做好前台HTML、CSS样式&#xff0c;代码如下&a…

如何用Vue实现简易的富文本编辑器,并支持Markdown语法

前端开发经常会用到富文本编辑器&#xff0c;比如CKEditor&#xff0c;动不动一个库几十M的代码量&#xff0c;其中涉及许多你可能用不到的功能特性和相关设置&#xff0c;CKEditor最新版本的代码仓库就有接近2000个JS文件&#xff0c;300,000行代码。 可是如果你只需要一个简…

互联网基建成果,快速实现一个clubhouse要多久

最近国外的一款基于语音的社交软件clubhouse掀起了一股热潮&#xff0c;尤其是在Eleon Musk的带动下&#xff0c;整个互联网圈内人都在第一时间抢先体验。不管它为什么会火&#xff0c;肯定不是技术上有什么特别的优势。随着整个互联网技术生态的不断发展&#xff0c;互联网基础…

阿里帝国到底有多庞大

马云&#xff0c;男&#xff0c;1964年9月10日生于浙江省杭州市&#xff0c;祖籍浙江省嵊州市谷来镇&#xff0c; 阿里巴巴集团主要创始人&#xff0c;现担任阿里巴巴集团董事局主席、日本软银董事、TNC中国理事会主席兼全球董事会成员、华谊兄弟董事、生命科学突破奖基金会董事…

如何搭建一个内部组件共享平台

如今前端越来越趋于组件化的开发方式&#xff0c;最大的益处就是UI页面和逻辑的共用。在开发者的眼里&#xff0c;如果你打开一个网站&#xff0c;组件化的开发方式会让你看起来像这个样子&#xff1a;逻辑功能上我们会封装成一个库&#xff0c;然后NPM发布到公共仓库上&#x…

不要讨厌HATEOAS

或我如何学会不再担心和爱HATEOAS REST已成为实现Web服务的事实上的解决方案&#xff0c;至少已成为一种流行的解决方案。 这是可以理解的&#xff0c;因为REST在使用HTTP规范时提供了一定程度的自我文档。 它经久耐用&#xff0c;可扩展&#xff0c;并提供了其他一些理想的特…

前端如何进行日志驱动开发

日志在开发过程中的作用自不必说&#xff0c;一旦程序出现问题&#xff0c;我们首先想到的是通过日志监控去追查。 好的日志可以通过应用程序执行的历史记录模拟出用户在使用程序的时候操作的完整过程。 想知道发生了什么 为了便于我们分析程序哪里出现问题&#xff0c;我们…