- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
几周前,我被要求创建一个在 Google Cloud Platform 上运行的 Web 应用程序(在撰写本文时 SDK v1.9.48)。配置 AppEngine 设置(创建帐户、项目、云数据库、源代码存储库等)后,我准备使用 GAE Eclipse 插件开发我的第一个 Web 应用程序。
当我发现 GAE 仅默认支持 JSP 和 servlet 时,我感到非常失望。
然后我说:“愿上帝帮助我!又回到 J2EE 的石器时代了吗?我习惯了 JSF 和 (C)DI 的 UI。我如何将这 3 个 J2EE 标准和 (C)DI 集成到 GAE Web 应用程序中?让它顺利运行(如果可能的话)?”:
只要继续阅读这篇文章,您就会知道如何做!
最佳答案
好吧,我决定不那么轻易放弃并陷入这个问题。经过几周的努力研究和试错编码,我找到了解决这个困惑问题的方法。
在开始这篇文章之前,我将为您提供一些很棒的资源,可以帮助您将其整合在一起:
框架:
这就是我让它工作的方法:
最重要的配置位于 web.xml 中。 JSF 初始化必须首先运行:我发现 com.sun.faces.config.ConfigureListener
负责这一步,它总是寻找 FacesServlet
声明。由于 JSF 请求必须由 Guice 提供 FacesHttpServlet
包装器(我稍后会发布)以启用 DI,然后:
FacesServlet
没有 <servlet-mapping>
s(我通过试错编码找出了该步骤)。它只是声明来初始化 FacesContextFactory
。这是 web.xml 必须具备的结构:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>BrochureForce</display-name>
<description>Purchase orders generator configured to run on the Google AppEngine.</description>
<context-param>
<description>Project stage (Development or Production)</description>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<description>
Designate client-side state saving, since GAE doesn't handle
server side (JSF default) state management.
</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<description>Sets the default suffix for JSF pages to .xhtml</description>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<description>
When enabled, the runtime initialization and default ResourceHandler
implementation will use threads to perform their functions. Set this
value to false if threads aren't desired (as in the case of single-threaded
environments such as the Google AppEngine).
Note that when this option is disabled, the ResourceHandler will not
pick up new versions of resources when ProjectStage is development.
</description>
<param-name>com.sun.faces.enableThreading</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<description>Allows dependency-injection into ManagedBeans</description>
<param-name>com.sun.faces.injectionProvider</param-name>
<param-value>mypackage.jsf.JsfInjectionProvider</param-value>
</context-param>
<context-param>
<description>Specify JBoss Expression Language Over Default</description>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
<!-- JSF INITIALIZATION GOES FIRST!! -->
<servlet>
<description>
JSF 2 Servlet. There's NO servlet-mapping defined for this servlet because
it's declared here in order to enforce the FacesFactory to load properly
so that an instance of this servlet can be injected in the FacesHttpServlet
used by Guice to serve JSF requests and as injection provider at the same time.
Furthermore, the "load-on-startup" property is set to "0" to tell Jetty
that this servlet MUST be loaded first.
</description>
<servlet-name>JSF Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<listener>
<description>JSF Initialization.</description>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<!-- JSF INITIALIZATION GOES FIRST!! -->
<listener>
<description>PERSISTENCE ENGINE INITIALIZATION AND SHUTDOWN.</description>
<listener-class>mypackage.listener.PersistenceManagerSetupListener</listener-class>
</listener>
<!-- ***** Specify session timeout of thirty (30) minutes. ***** -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- **************************************************** -->
<!-- DI API initialization (Google Guice Implementation). -->
<!-- **************************************************** -->
<filter>
<description>Google Guice filter which enables DI.</description>
<filter-name>GuiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GuiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<description>
This listener initializes the Guice injector and wraps the JSF Servlet
into a HttpServlet in order to serve JSF requests via Guice Filter.
</description>
<listener-class>mypackage.listener.GuiceListener</listener-class>
</listener>
<!-- **************************************************** -->
</web-app>
其次,我不再尝试将托管 Bean 实例注入(inject)另一个实例。相反,我将绑定(bind)的业务逻辑实例注入(inject)到 Bean 中(换句话说,模拟 EJB 行为)。这就是我所做的:
我定义了 @BindingAnnotation
业务逻辑实现:
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@Documented
@BindingAnnotation
@Retention(RUNTIME)
@Target({ TYPE })
public @interface BusinessLogic {}
我定义了一个业务逻辑接口(interface)及其实现,并用 @BusinessLogic
进行了注释。注解(这是一个注册页面访问的例子,字段为:访问次数、源IP、时间戳):
import java.util.List;
import mypackage.annotation.BusinessLogic;
import mypackage.dataaccess.entity.Visit;
@BusinessLogic
public interface VisitsHandler {
public void insertVisit();
public List<Visit> getPageVisits();
// Propiedades
public String getCurrentVisit();
public void setCurrentVisit(String currentVisit);
}
及其实现:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import mypackage.annotation.BusinessLogic;
import mypackage.jsf.logic.VisitsHandler;
import mypackage.dataaccess.PersistenceManager;
import mypackage.dataaccess.Queries;
import mypackage.dataaccess.entity.Visit;
@BusinessLogic
public class VisitsHandlerImpl implements VisitsHandler {
private String currentVisit;
public void insertVisit() {
PersistenceManager pMgr = PersistenceManager.getInstance();
Visit newVisit = new Visit();
newVisit.setUserIp("127.0.0.1");
newVisit.setTimestamp(new Date(System.currentTimeMillis()));
pMgr.insert(newVisit);
pMgr = null; // Dereference the singleton instance.
this.currentVisit = newVisit.toString();
}
@SuppressWarnings("rawtypes")
public List<Visit> getPageVisits() {
PersistenceManager pMgr = PersistenceManager.getInstance();
List<Visit> visitsList = new ArrayList<Visit>();
List visits = pMgr.executeJpqlQuery(Queries.JPQL_VISITS);
for (Object v : visits) {
visitsList.add((Visit) v);
}
pMgr = null; // Dereference the singleton instance.
return visitsList;
}
/**
* @return the currentVisit
*/
public String getCurrentVisit() {
return currentVisit;
}
/**
* @param currentVisit
* the currentVisit to set
*/
public void setCurrentVisit(String currentVisit) {
this.currentVisit = currentVisit;
}
}
为了避免重新实例化业务逻辑对象,我为 DI 绑定(bind)定义了一个实例:
import mypackage.jsf.logic.VisitsHandler;
import mypackage.jsf.logic.impl.VisitsHandlerImpl;
interface InjectorConstants {
// Url patterns for FacesServlet, as it would be defined in web.xml
static String[] JSF_SERVLET_URL_PATTERNS = new String[] { "*.jsf", "*.xhtml" };
// BUSINESS LOGIC OBJECTS.
static Class<VisitsHandler> VISITS_HANDLER = VisitsHandler.class;
static VisitsHandler VISITS_HANDLER_IMPL = new VisitsHandlerImpl();
}
现在,带有对象绑定(bind)的 Guice 模块:
import javax.faces.webapp.FacesServlet;
import javax.inject.Singleton;
import mypackage.cdi.annotation.ViewScoped;
import mypackage.cdi.annotation.ViewScopedImpl;
import mypackage.cdi.listener.PostConstructTypeListener;
import mypackage.jsf.FacesHttpServlet;
import com.google.inject.matcher.Matchers;
import com.google.inject.servlet.ServletModule;
public class JSFModule extends ServletModule {
private void businessLogicBindings() {
bind(InjectorConstants.VISITS_HANDLER).toInstance(InjectorConstants.VISITS_HANDLER_IMPL);
}
private void systemBindings() {
// Add support for the @PostConstruct annotation for Guice-injected
// objects.
bindListener(Matchers.any(), new PostConstructTypeListener(null));
// Binding a custom implementation of "@ViewScoped" scope.
bindScope(ViewScoped.class, new ViewScopedImpl());
}
private void jsfBindings() {
// Define and bind FacesServlet as singleton object
// so it can be injected in FacesHttpServlet's constructor.
bind(FacesServlet.class).in(Singleton.class);
// JSF patterns to be served by FacesHttpServlet.
for (String urlPattern : InjectorConstants.JSF_SERVLET_URL_PATTERNS) {
serve(urlPattern).with(FacesHttpServlet.class);
}
}
@Override
protected void configureServlets() {
// Guice injector bindings.
this.systemBindings();
this.businessLogicBindings();
this.jsfBindings();
}
}
businessLogicBindings()
方法将业务逻辑接口(interface)与实现实例相关联。另一方面,您可以在这一行看到:serve(urlPattern).with(FacesHttpServlet.class);
,Guice 将使用注入(inject)的 FacesServlet
将 JSF 请求重新路由到 HttpServlet 包装器。实例:
import java.io.IOException;
import javax.faces.webapp.FacesServlet;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Singleton
public class FacesHttpServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final Servlet facesServlet;
@Inject
public FacesHttpServlet(FacesServlet facesServlet) {
this.facesServlet = facesServlet;
}
@Override
public void init(ServletConfig config) throws ServletException {
this.facesServlet.init(config);
}
@Override
public ServletConfig getServletConfig() {
return this.facesServlet.getServletConfig();
}
@Override
public String getServletInfo() {
return this.facesServlet.getServletInfo();
}
@Override
public void destroy() {
super.destroy();
this.facesServlet.destroy();
}
@Override
public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
HttpServletRequest httpReq = (HttpServletRequest) req;
String reqUrl = httpReq.getRequestURL().toString();
// A hack to redirect the index page. It's been throwing an error if the
// "/index.[xhtml|jsf]" is not explicitly specified in the request URL.
if(reqUrl.toLowerCase().endsWith("index.xhtml")) {
((HttpServletResponse) resp).sendRedirect(reqUrl.replace("index.xhtml", "index.jsf"));
} else {
this.facesServlet.service(req, resp);
}
}
}
现在,初始化注入(inject)器的监听器:
import java.util.HashMap;
import mypackage.cdi.JSFModule;
import mypackage.cdi.JsfInjectionProvider;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
public class GuiceListener extends GuiceServletContextListener {
protected AbstractModule module;
protected static Injector injector;
private static HashMap<String, Object> instancesMap;
public GuiceListener() {
// Bean instance list to ensure that we inject a unique bean instance.
instancesMap = new HashMap<>();
// Create the injector.
injector = Guice.createInjector(new JSFModule());
}
@Override
public Injector getInjector() {
return injector;
}
/**
* given a class, generates an injected instance. Useful when an API call is
* needed internally.
*/
public static <T> T getInstance(Class<T> type) {
return injector.getInstance(type);
}
/**
* given an injectable instance, injects its dependencies and make sure to
* only inject one.
*/
public static void injectMembers(Object instance) {
Object obj = null;
if (JsfInjectionProvider.isBusinessLogicObject(obj)) {
String instanceClassName = instance.getClass().getName();
Object mappedInstance = instancesMap.get(instanceClassName);
if (mappedInstance == null) {
// It's a new bean instance. It's stored in the bean map
// to be able to reuse it.
instancesMap.put(instanceClassName, instance);
obj = instance;
} else {
// There's already a bean instance. Let's reuse it!.
obj = mappedInstance;
}
} else { // it should be a managed bean.
obj = instance;
}
injector.injectMembers(obj);
}
}
最后但并非最不重要的一点是,Mojarra 必须将我们的 DI 实现注册为其 DI 提供程序(请参阅 <context-param>
com.sun.faces.injectionProvider
值):
import javax.faces.bean.ManagedBean;
import mypackage.cdi.annotation.BusinessLogic;
import mypackage.cdi.listener.GuiceListener;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.vendor.WebContainerInjectionProvider;
public class JsfInjectionProvider extends WebContainerInjectionProvider {
@Override
public void inject(Object obj) throws InjectionProviderException {
if (isManagedBean(obj) || isBusinessLogicObject(obj)) {
GuiceListener.injectMembers(obj);
}
}
/**
* As an arbitrary choice, the choice here is to inject only into
* {@code @ManagedBean} instances, so that other classes - not written by us
* - wouldn't be injected too. This choice could be altered.
*
* @param obj
* A JSF bean instance (annotated with @ManagedBean).
* @return
*/
private boolean isManagedBean(Object obj) {
return obj != null && obj.getClass().getAnnotation(ManagedBean.class) != null;
}
public static boolean isBusinessLogicObject(Object obj) {
return obj != null && obj.getClass().getAnnotation(BusinessLogic.class) != null;
}
}
所有这些都可以正常工作(但省略了 JPA 部分,此时该部分不相关): ExampleBean
:
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.inject.Inject;
import mypackage.jsf.logic.VisitsHandler;
import mypackage.dataaccess.entity.Visit;
@ManagedBean(name="jsfbExample")
public class ExampleBean implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private VisitsHandler visitsHandler;
@PostConstruct
public void init() {
System.out.println("ExampleBean - Injection works! visitsHandler = " + visitsHandler); // It works.
}
/**
* Method to test EL engine processing with parameters.
* @param param
* @return
*/
public void insertVisit() {
this.visitsHandler.insertVisit();
}
public List<Visit> getPageVisits() {
return this.visitsHandler.getPageVisits();
}
/**
* @return the currentVisit
*/
public String getCurrentVisit() {
return this.visitsHandler.getCurrentVisit();
}
/**
* @param currentVisit
* the currentVisit to set
*/
public void setCurrentVisit(String currentVisit) {
this.visitsHandler.setCurrentVisit(currentVisit);
}
}
现在,您可以创建一个 *.xhtml 文件作为索引,并将此测试代码放在上面:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head id="head">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Welcome to JSF 2.1 on the Google AppEngine!</title>
</h:head>
<h:body>
<h:form>
<h:outputText id="lastVisit" value="#{jsfbExample.currentVisit}" /><br/>
<h:commandButton value="New visit!"
actionListener="#{jsfbExample.insertVisit()}">
<f:ajax execute="@this" render="pageVisitsList" />
</h:commandButton>
<h:commandButton value="Last inserted visit!">
<f:ajax execute="@this" render="lastVisit" />
</h:commandButton>
<h:panelGrid id="pageVisitsList">
<c:forEach var="visit" items="#{jsfbExample.pageVisits}">
<h:outputText value="#{visit.toString()}" />
</c:forEach>
</h:panelGrid>
</h:form>
</h:body>
</html>
JPA 功能更容易,因为它的配置既不依赖于 JSF 也不依赖于 DI。 PersistenceManagerSetupListener
:
package mypackage.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import mypackage.dataaccess.PersistenceManager;
import mypackage.utils.StringMap;
public class PersistenceManagerSetupListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextInitEvt) {
// This is only a wrapper over HashMap<String, String>
StringMap initProperties = new StringMap();
// Check the System properties to determine if we are running on cloud
// or not, and set up the JDBC driver accordingly.
String platform = System.getProperty("com.google.appengine.runtime.version").toLowerCase()
.contains("google app engine") ? "cloud" : "dev";
initProperties.put("datanucleus.ConnectionURL", System.getProperty(platform + ".db.url"));
initProperties.put("datanucleus.ConnectionDriverName", System.getProperty(platform + ".db.driver"));
initProperties.put("datanucleus.ConnectionUserName", System.getProperty(platform + ".db.user"));
initProperties.put("datanucleus.ConnectionPassword", System.getProperty(platform + ".db.password"));
// I implemented password encryption. See Datanucleus' "ConnectionEncryptionProvider" interface documentation.
initProperties.put("datanucleus.ConnectionPasswordDecrypter",
System.getProperty(platform + ".db.encryptionProvider"));
// ***********************************************************************************************************
// THESE 2 ARE A MUST-HAVE!!!
// ***********************************************************************************************************
initProperties.put("datanucleus.identifier.case", System.getProperty("persistencemanager.identifier.case"));
initProperties.put("datanucleus.storeManagerType", System.getProperty("persistencemanager.storeManagerType"));
// ***********************************************************************************************************
initProperties.put("datanucleus.NontransactionalRead",
System.getProperty("persistencemanager.NontransactionalRead"));
initProperties.put("datanucleus.NontransactionalRead",
System.getProperty("persistencemanager.NontransactionalRead"));
initProperties.put("datanucleus.NontransactionalWrite",
System.getProperty("persistencemanager.NontransactionalWrite"));
initProperties.put("datanucleus.singletonEMFForName",
System.getProperty("persistencemanager.singletonEMFForName"));
initProperties.put("javax.persistence.query.timeout", System.getProperty("persistencemanager.query.timeout"));
initProperties.put("datanucleus.datastoreWriteTimeout",
System.getProperty("persistencemanager.datastoreWriteTimeout"));
// Initialize persistence engine.
PersistenceManager.initialize(initProperties);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextDestroyedEvt) {
PersistenceManager.shutdown();
}
}
所有持久化初始化属性均在 app-engine.xml
中定义。 。其基本结构:
<appengine-web-app ...>
<application>cloud-project-id</application>
<version>1</version>
<threadsafe>true</threadsafe>
<system-properties>
<!-- Cloud platform properties (their name starts with "cloud") -->
<property name="cloud.db.url"
value="jdbc:google:mysql://(cloud-connection-name)/(db-name)" />
<property name="cloud.db.driver"
value="com.google.appengine.api.rdbms.AppEngineDriver" />
<!-- ... -->
<!-- Dev platform properties (their name starts with "dev") -->
<property name="dev.db.url" value="jdbc:mysql://(db-server):(db-port)/(db-name)" />
<property name="dev.db.driver" value="com.mysql.jdbc.Driver" />
<!-- ... -->
<!-- Datanucleus properties -->
<!-- *********************************************** -->
<!-- THESE 2 ARE A MUST-HAVE!!! Others are optional -->
<!-- *********************************************** -->
<property name="persistencemanager.storeManagerType" value="rdbms" />
<!-- This means that all DB identifiers MUST be defined in lowercase. -->
<property name="persistencemanager.identifier.case" value="LowerCase" />
<!-- *********************************************** -->
<!-- ... -->
</system-properties>
<sessions-enabled>true</sessions-enabled>
<async-session-persistence enabled="false" />
<static-files>
<exclude path="/**.xhtml" />
</static-files>
</appengine-web-app>
您必须至少定义一个持久性单元(在“persistence.xml”中):
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="MyPersistenceUnit">
<!-- DATANUCLEUS' JPA 2.0 PERSISTENCE PROVIDER CLASS -->
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<!-- ENTITY CLASSES -->
<class>mypackage.dataaccess.entity.Visit</class>
<!-- DON'T PROCESS UNLISTED CLASSES AS ENTITY CLASSES. -->
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>
以及持久性管理器对象中的一些初始化和关闭方法,用于创建和销毁 EntityManagerFactory 和 EntityManager。像这样的事情:
public static void initialize(Map properties) {
if (!isInitialized) {
if (properties == null) {
emfInstance = Persistence.createEntityManagerFactory("MyPersistenceUnit");
} else {
emfInstance = Persistence.createEntityManagerFactory("MyPersistenceUnit", properties);
}
emInstance = emfInstance.createEntityManager();
isInitialized = true;
}
}
public static void shutdown() {
try {
emInstance.close();
} catch (Exception e) {}
try {
emfInstance.close();
} catch (Exception e) {}
}
“Visit”类只是一个实体类,它映射 3 个字段(访问次数、源 IP 和时间戳),并注册在“persistence.xml”文件中。
我将这篇文章作为教程编写,逐步展示了我如何设法在 GAE 上运行这些技术(当我输入这些行时,SDK 1.9.48)。我花了数周的时间进行研究和试错编码,我希望本指南能够帮助其他 Java 程序员避免像我一样经历这种困惑。
希望本指南可以帮助其他人在 GAE 中创建出色的 J2EE 应用程序。
关于java - 如何设置具有 JSF 2.2、JPA 2.0 和依赖注入(inject)功能的 Google AppEngine Web 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41786164/
我正在构建一个 RCP 应用程序,其中每个季度都会更新功能/插件。因此,如果用户选择自动更新功能/插件,则会下载更新插件的新 jar,但旧插件仍在使用我不再使用的磁盘空间。 我厌倦了删除包含旧 jar
我如何从外部 Controller 功能中调用 Controller 内部的功能,例如电话间隙回调功能 这是 Controller 外部定义的功能 function onDeviceReady()
如果某个功能(例如 MediaSource)可用,我如何使用 Google Dart 检查。 new MediaSource() 抛出一个错误。如何以编程方式检查此类或功能是否存在?有任何想法吗?是否
我正在尝试运行 Azure Orchestrations,突然我开始从 statusQueryGetUri 收到错误: 协调器函数“UploadDocumentOrchestrator”失败:函数“U
我见过 iPhone 上的应用程序,如果在 3.0 上运行,将使用 3.0 功能/API,例如应用内电子邮件编辑器,如果在 2.x 上运行,则不使用这些功能,并退出应用程序以启动邮件相反。 这是怎么做
这是 DB 规范化理论中的一个概念: Third normal form is violated when a non-key field is a fact about another non-ke
如果我定义 #if SOMETHING #endif 而且我还没有在任何地方定义 SOMETHING。 #if 中的代码会编译吗? 最佳答案 当#if的参数表达式中使用的名称未定义为宏时(在所有其他宏
我刚刚澄清了 A* 路径查找应该如何在两条路径具有相等值的 [情况] 下运行,无论是在计算期间还是在结束时,如果有两条相等的短路径。 例如,我在我的起始节点,我可以扩展到两个可能的节点,但它们都具有相
Java有没有类似下面的东西 宏 一种遍历所有私有(private)字段的方法 类似于 smalltalk symbols 的东西——即用于快速比较静态字符串的东西? 请注意,我正在尝试为 black
这个程序应该将华氏度转换为摄氏度: #include int main() { float fahrenheit, celsius; int max, min, step;
当打开PC缓存功能后, 软件将采用先进先出的原则排队对示波器采集的每一帧数据, 进行帧缓存。 当发现屏幕中有感兴趣的波形掠过时, 鼠标点击软件的(暂停)按钮, 可以选择回看某一帧的波形
我有一个特殊的(虚拟)函数,我想在沙盒环境中使用它: disable.system.call eval(parse(text = 'model.frame("1 ~ 1")'), envir = e
使用新的 Service 实现,我是否必须为我的所有服务提供一个 Options 方法? 使用我的所有服务当前使用的旧 ServiceBase 方法,OPTIONS 返回 OK,但没有 Access-
我正在阅读 Fogus 的关于 Clojure 的喜悦的书,在并行编程章节中,我看到了一个函数定义,它肯定想说明一些重要的事情,但我不知道是什么。此外,我看不到这个函数有什么用 - 当我执行时,它什么
我有大量的 C 代码,大部分代码被注释掉和/或 #if 0。当我使用 % 键匹配 if-else 的左括号和右括号时,它也匹配注释掉的代码。 有没有办法或vim插件在匹配括号时不考虑注释掉或#if 0
我有这个功能: map(map(fn x =>[x])) [[],[1],[2,3,4]]; 产生: val it = [[],[[1]],[[2],[3],[4]]] 我不明白这个功能是如何工作的。
我使用 Visual Studio 代码创建了一个函数应用程序,然后发布了它。功能应用程序运行良好。我现在在功能门户中使用代码部署功能(KUDU)并跳过构建。下面是日志 9:55:46 AM
我有一个数据框df: userID Score Task_Alpha Task_Beta Task_Charlie Task_Delta 3108 -8.00 Easy Easy
我真的无法解决这个问题: 我有一个返回数据框的函数。但是,数据框仅打印在我的控制台中,尽管我希望将其存储在工作空间中。我怎样才能做到这一点? 样本数据: n <- 32640 t <- seq(3*p
有没有办法找出所有可能的激活器命令行选项? activator -help仅提供最低限度的可用选项/功能列表,但所有好的东西都隐藏起来,即使在 typesafe 网站在线文档中也不可用。 到目前为止,
我是一名优秀的程序员,十分优秀!