GVKun编程网logo

使用JSF 2.0在命名容器内获取组件clientId的完整前缀

5

在本文中,我们将为您详细介绍使用JSF2.0在命名容器内获取组件clientId的完整前缀的相关知识,此外,我们还会提供一些关于@FeignClient注解中属性contextId的使用说明、ajax

在本文中,我们将为您详细介绍使用JSF 2.0在命名容器内获取组件clientId的完整前缀的相关知识,此外,我们还会提供一些关于@FeignClient注解中属性contextId的使用说明、ajax – 如何处理循环命名容器中的组件、android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2、Android+PHP 使用HttpClient提交POST的请求,使用JSON解析响应的有用信息。

本文目录一览:

使用JSF 2.0在命名容器内获取组件clientId的完整前缀

使用JSF 2.0在命名容器内获取组件clientId的完整前缀

我正在通过JSF中的AJAX更新组件:

<h:form>    <h:outputLink>Click me        <f:ajax event="click" render=":messages" />    </h:outputLink></h:form><h:messages id="messages" globalOnly="true" />

由于<h:messages />居住在外面,<h:form />我必须在ID前面加上冒号(:)。这可行。

但是,如果我将相同的代码放入组件中并将该组件包括到我的页面中,则代码将失败。原因是:messages声明是指组件层次结构的根,而<h:messages/>我要更新的组件实际上位于我的自定义组件下,该组件位于页面下(因此位置为style):myComponent:messages

在组件内部,如何获得<h:messages/>组件的正确前缀?我知道我可以手动将ID分配给我的组件,并使用该ID为引用添加前缀(例如:#{cc.attrs.id}:messages)。但是,我不知道此组件位于组件层次结构的哪个级别,因此所需的前缀甚至可能是:foo:bar:x:y:messages

答案1

小编典典

似乎您可以通过表达式语言(EL)隐式对象(cccomponent)访问当前前缀:

  • cc.clientId返回当前 复合 组件的前缀
  • component.clientId 返回任何当前组件的前缀。

例如,在页面中,通过

<myComponent id="foo">

在此组件内部,可以像这样获取客户端ID:

<h:outputText id="bar">   <p>ClientId for the composite component: #{cc.clientId}</p>   <p>ClientId for current any component: #{component.clientId}</p></h:outputText>

以下内容应打印为:

ClientId for the composite component: fooClientId for current any component: foo:bar

我从博客文章JSF中获得了指针:使用组件标识符(id /
clientId)。它声明这是JSF 2.0的新功能。在此之前,人们必须以编程方式从备用Bean中获取ID。

@FeignClient注解中属性contextId的使用说明

@FeignClient注解中属性contextId的使用说明

一、概述

如果我们使用Feign定义了两个接口,但是目标服务是同一个,那么在SpringBoot启动时就会遇到一个问题:

Description:
The bean ''xxxxxxxx.FeignClientSpecification'', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

二、解决方案

2.1 方案1

修改yml配置:spring.main.allow-bean-definition-overriding=true

spring:
  main:
    allow-bean-definition-overriding: true

2.2 方案2

在每个Feign的接口中,在注解上加 contextId属性

contextId在Feign Client的作用是在注册Feign Client Configuration的时候需要一个名称,名称是通过getClientName方法获取的

@FeignClient(name = "sale-service",contextId= "saleservice1")
 
public interface saleClient{
 
    @RequestMapping(value = "/sale/add", method = RequestMethod.GET)
 
    String add(@RequestParam("saleNum") String queryStr);
 
}

备注:contextId= "名称" 中的名称,不能用“_”会报错,可以用“-”

三、源代码分析

  • 包名:spring-cloud-openfeign-core-2.2.5.RELEASE.jar
  • 类路径:org.springframework.cloud.openfeign.FeignClientsRegistrar

相关代码1

 private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
        String className = annotationMetadata.getClassName();
        BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
        this.validate(attributes);
        definition.addPropertyValue("url", this.getUrl(attributes));
        definition.addPropertyValue("path", this.getPath(attributes));
        String name = this.getName(attributes);
        definition.addPropertyValue("name", name);
        String contextId = this.getContextId(attributes);
        definition.addPropertyValue("contextId", contextId);
        definition.addPropertyValue("type", className);
        definition.addPropertyValue("decode404", attributes.get("decode404"));
        definition.addPropertyValue("fallback", attributes.get("fallback"));
        definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
        definition.setAutowireMode(2);
        String alias = contextId + "FeignClient";
        AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
        beanDefinition.setAttribute("factoryBeanObjectType", className);
        boolean primary = (Boolean)attributes.get("primary");
        beanDefinition.setPrimary(primary);
        String qualifier = this.getQualifier(attributes);
        if (StringUtils.hasText(qualifier)) {
            alias = qualifier;
        }
 
        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
    }

代码截图:

相关代码2

可以看到, name应该是从注解中的属性取值来的, 再看看getClientName()方法.

 private String getClientName(Map<String, Object> client) {
        if (client == null) {
            return null;
        } else {
            String value = (String)client.get("contextId");
            if (!StringUtils.hasText(value)) {
                value = (String)client.get("value");
            }
 
            if (!StringUtils.hasText(value)) {
                value = (String)client.get("name");
            }
 
            if (!StringUtils.hasText(value)) {
                value = (String)client.get("serviceId");
            }
 
            if (StringUtils.hasText(value)) {
                return value;
            } else {
                throw new IllegalStateException("Either ''name'' or ''value'' must be provided in @" + FeignClient.class.getSimpleName());
            }
        }
    }

代码截图:

一目了然了, 我们声明@FeignClient注解时, 只使用了value属性, 所以产生了冲突, 只要加上contextId就好了.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

您可能感兴趣的文章:
  • @FeignClient path属性路径前缀带路径变量时报错的解决
  • 解决@RequestMapping和@FeignClient放在同一个接口上遇到的坑
  • @FeignClient 实现简便http请求封装方式
  • SpringCloud全面解析@FeignClient标识接口的过程
  • 通过Feign进行调用@FeignClient 找不到的解决方案
  • 浅谈@FeignClient中name和value属性的区别

ajax – 如何处理循环命名容器中的组件

ajax – 如何处理循环命名容器中的组件

我有以下结构(内容和属性省略):
<ui:repeat id="outerlist">
    <my:compositeComponent id="myCC">
        <h:panelgroup id="container">
            Some content here (outputText,etc.)
            <ui:repeat id="innerlist">
               <h:commandButton>
                   <f:ajax render=":#{cc.clientId}:container" />

<!-- all closing tags accordingly -->

由于容器内的内容取决于内部列表按钮的操作,我需要更新它.当没有外部ui:重复时,如上所示的方法起作用.但是,如果存在组件未找到错误,则会失败.

这似乎是因为cc.clientId本身包含外部ui:repeat的行索引,例如,outerlist:0:myCC:容器.如a comment to this answer所示,该索引ID在视图树的服务器端表示中不可用.而是“行索引仅存在于客户端”.我必须承认,我不太明白这个索引是如何完成的以及服务器端的可用内容.

所以我的问题是:JSF如何进行这种索引,它(在服务器上)如何将ui内部的不同“实例”分开:重复,是否有解决方案,我想用上面的代码实现什么?

< f:ajax>中指定的客户端ID必须在JSF的服务器端都可用
facesContext.getViewRoot().findComponent(clientId);

(因此可以找到它以便为ajax响应呈现其新的HTML表示)

并在JavaScript的客户端

document.getElementById(clientId);

(一旦新的HTML内容的ajax响应到达,它就可以被JS更新/替换)

作为< ui:repeat>仅在视图呈现时间内运行,具有行索引的客户机ID不代表服务器端的有效组件(来自findComponent()的“无法找到组件…”错误),但它确实表示客户端中的有效HTML元素侧.基本上,您需要客户端ID,而不需要服务器端的行索引和客户端的行索引.但这不适用于< ui:repeat>因为它(不幸的是)不可能通过单独的findComponent()来选择特定迭代轮次的组件树状态.

使用JSTL< c:forEach>时它应该可以正常工作并且在视图构建期间运行时动态分配组件ID,并且实际上在视图树中生成多个值得满足的JSF组件,而不是仅在渲染期间多次重复使用的组件.

<c:forEach varStatus="loop">
    <my:compositeComponent id="myCC">
        <h:panelGroup id="container_#{loop.index}">
            Some content here (outputText,etc.)
            <ui:repeat id="innerlist_#{loop.index}">
               <h:commandButton>
                   <f:ajax render=":#{cc.clientId}:container_#{loop.index}" />

然而,这有其自身的含义,当然与复合组件一起使用时,以及在嵌套循环中使用时也是如此.您的代码不够完整,无法提供有关该代码的见解和建议.例如,当将这段代码放置在复合组件中时,它会断开,复合组件本身也在渲染时循环中重复使用多次.

也可以看看:

> JSTL in JSF2 Facelets… makes sense?
> How to find out client ID of component for ajax update/render? Cannot find component with expression “foo” referenced from “bar”

android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2

android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2

我正尝试使用 Angularjs(使用Ionic Framework)通过Google OAuth2从我的Phonegap应用程序登录.目前我正在使用 http://phonegap-tips.com/articles/google-api-oauth-with-phonegaps-inappbrowser.html进行登录.但是当我使用Angular-UI-Router for Ionic时,它正在创建非常难看的代码和相当难以理解的代码.

如果没有任何正确的答案,这个问题似乎正在蔓延.我希望现在应该解决. Google Angular Guys应该会有所帮助.
How to implement Google Auth in phonegap?

最接近的主题是How to use Google Login API with Cordova/Phonegap,但这不是angularjs的解决方案.

我不得不使用以下代码传输javascript变量值:

var el = document.getElementById('test');
        var scopeTest = angular.element(el).scope();
        scopeTest.$apply(function(){ 
            scopeTest.user = user;
            scopeTest.logged_in = true;
            scopeTest.name = user.name;
            scopeTest.email = user.email;
        });

解决方法

我做了这样的解决方案,其中TestCtrl是Login Button所在的Controller.有一个基于jquery的$.ajax调用混合,我将改变为angualar方式. google_call函数基本上调用google_api,这在上面提到的phonegap-tips中提到的链接中提到.
.controller('TestCtrl',function($scope,$ionicPopup) {
$scope.logged_in = false;
$scope.getMember = function(id) {
    console.log(id);
};
$scope.test = function(){
    $ionicPopup.alert({"title":"Clicked"});
}

$scope.call_google = function(){
    googleapi.authorize({
    client_id: 'CLIENT_ID',client_secret: 'CLIENT_SECRET',redirect_uri: 'http://localhost',scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'
    }).done(function(data) {
        accesstoken=data.access_token;
        // alert(accesstoken);
        // $loginStatus.html('Access Token: ' + data.access_token);
        console.log(data.access_token);
        //$ionicPopup.alert({"title":JSON.stringify(data)});
        $scope.getDataProfile();
    });
};
$scope.getDataProfile = function(){
    var term=null;
    //  alert("getting user data="+accesstoken);
    $.ajax({
           url:'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token='+accesstoken,type:'GET',data:term,dataType:'json',error:function(jqXHR,text_status,strError){
           },success:function(data)
           {
           var item;

           console.log(JSON.stringify(data));
           // Save the userprofile data in your localStorage.
           window.localStorage.gmailLogin="true";
           window.localStorage.gmailID=data.id;
           window.localStorage.gmailEmail=data.email;
           window.localStorage.gmailFirstName=data.given_name;
           window.localStorage.gmailLastName=data.family_name;
           window.localStorage.gmailProfilePicture=data.picture;
           window.localStorage.gmailGender=data.gender;
           window.localStorage.gmailName=data.name;
           $scope.email = data.email;
           $scope.name = data.name;
           }
        });
        //$scope.disconnectUser(); //This call can be done later.
};
$scope.disconnectUser = function() {
  var revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token='+accesstoken;

  // Perform an asynchronous GET request.
  $.ajax({
    type: 'GET',url: revokeUrl,async: false,contentType: "application/json",dataType: 'jsonp',success: function(nullResponse) {
      // Do something Now that user is disconnected
      // The response is always undefined.
      accesstoken=null;
      console.log(JSON.stringify(nullResponse));
      console.log("-----signed out..!!----"+accesstoken);
    },error: function(e) {
      // Handle the error
      // console.log(e);
      // You Could point users to manually disconnect if unsuccessful
      // https://plus.google.com/apps
    }
  });
};
})

我正在为尝试使用Google OAuth2登录时面临类似问题的新手提供此答案.因此,我无耻地要求UpVotes,因为我也是新来的!

Android+PHP 使用HttpClient提交POST的请求,使用JSON解析响应

Android+PHP 使用HttpClient提交POST的请求,使用JSON解析响应

       这里介绍一下如何让自己的android程序具有联网功能。当然首先要有一台服务器,如果只是进行测试的话,可以使用局域网代替(手机连电脑wifi)。

要求电脑已配置好Apache+PHP环境。

       下面是一个简单的Android程序,相信只要有一定的Java基础就能大概“猜懂”其中的含义。(程序可能写的不够完善)

Android程序

布局文件

立即学习“PHP免费学习笔记(深入)”;

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/&lt;strong&gt;Activity&lt;/strong&gt;_vertical_margin" android:paddingleft="@dimen/&lt;strong&gt;Activity&lt;/strong&gt;_horizontal_margin" android:paddingright="@dimen/&lt;strong&gt;Activity&lt;/strong&gt;_horizontal_margin" android:paddingtop="@dimen/&lt;strong&gt;Activity&lt;/strong&gt;_vertical_margin" tools:c android:orientation="vertical"><textview android:layout_width="match_parent" android:layout_height="wrap_content" android:>gravity="center"
        android:text="使用JSON解析"
        android:textSize="30sp"/&gt;
    
    <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:>gravity="center"&gt;
        
        <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="账号" android:textsize="20sp" android:layout_marginright="20dp"></textview><edittext android:id="@+id/et_id" android:layout_width="match_parent" android:layout_height="wrap_content"></edittext></linearlayout><linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:>gravity="center"&gt;
        
        <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码" android:textsize="20sp" android:layout_marginright="20dp"></textview><edittext android:id="@+id/et_psw" android:layout_width="match_parent" android:layout_height="wrap_content"></edittext></linearlayout><button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="登录"></button>
</textview></linearlayout>
登录后复制
MainActivity.java

package com.example.jsontest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.<strong>Apache</strong>.http.HttpEntity;
import org.<strong>Apache</strong>.http.HttpResponse;
import org.<strong>Apache</strong>.http.NameValuePair;
import org.<strong>Apache</strong>.http.client.HttpClient;
import org.<strong>Apache</strong>.http.client.entity.UrlEncodedFormEntity;
import org.<strong>Apache</strong>.http.client.methods.HttpPost;
import org.<strong>Apache</strong>.http.impl.client.DefaultHttpClient;
import org.<strong>Apache</strong>.http.message.BasicNameValuePair;
import org.<strong>Apache</strong>.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONObject;

import android.os.Bundle;
import android.os.Looper;
import android.support.v7.app.ActionBar<strong>Activity</strong>;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


public class Main<strong>Activity</strong> extends ActionBar<strong>Activity</strong> {
	EditText et_id;
	EditText et_psw;
	Button btn_login;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.<strong>Activity</strong>_main);
        
        initView();
    }
    
    private boolean check(String id, String psw) {
    	if("".equals(id) || "".equals(psw))
    		return false;
    	return true;
    }
    
    private void initView() {
    	et_id = (EditText)findViewById(R.id.et_id);
    	et_psw = (EditText)findViewById(R.id.et_psw);
    	btn_login = (Button)findViewById(R.id.btn_login);
    	
    	btn_login.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//获取用户输入的用户名和密码
				final String id = et_id.getText().toString().trim();
				final String psw = et_psw.getText().toString().trim();
				
				if(check(id, psw)) {
					new Thread() {
						public void run() {
							try {
								HttpPost post = new HttpPost("这里要改成服务器文件所在URL地址");
								//如果传递参数个数比较多,可以对传递的参数进行封装
								List<namevaluepair> params = new ArrayList<namevaluepair>();
								params.add(new BasicNameValuePair("id", id));
								params.add(new BasicNameValuePair("psw", psw));
								//设置请求参数
								post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
								
								HttpClient httpClient = new DefaultHttpClient();
								//发送POST请求
								HttpResponse response = httpClient.execute(post);
								//如果服务器成功地返回响应
								if(response.getStatusLine().getStatusCode() == 200) {
									//String msg = EntityUtils.toString(response.getEntity());
									HttpEntity entity = response.getEntity();
									InputStream is = entity.getContent();
									
									BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);
									StringBuilder sb = new StringBuilder();
									sb.append(reader.readLine() + "\n"); // 这里 “ + "\n" ”加不加似乎对结果没有什么影响
									
									String line = "0";
									while((line = reader.readLine()) != null) {
										sb.append(line + "\n"); // 这里 “ + "\n" ”加不加似乎对结果没有什么影响
									}
									is.close();
									
									//获取请求响应结果
									String result = sb.toString();
									System.out.println(result);
									
									//打包成JSON进行解析
									JSONArray jsonArray = new JSONArray(result);
									JSONObject jsonData = null;
									//返回用户ID,用户密码
									String userId = "";
									String userPsw = "";
									//使用List进行存储
									List<string> data = new ArrayList<string>();
									for(int i = 0; i 索引,根据<strong>索引</strong>获取值
										userPsw = jsonData.getString("userPsw"); //userPsw是来源于服务器端php程序响应结果res的<strong>索引</strong>,根据<strong>索引</strong>获取值
										data.add("用户ID:" + userId + ",用户密码:" + userPsw); //保存返回的值,可进行相应的操作,这里只进行显示
									}
									
									Looper.prepare();
									Toast.makeText(Main<strong>Activity</strong>.this, data.toString(), Toast.LENGTH_LONG).show();
									Looper.loop();
								}
								else {
									Looper.prepare();
									Toast.makeText(Main<strong>Activity</strong>.this, "登录失败", Toast.LENGTH_LONG).show();
									Looper.loop();
								}
							}
							catch(<strong>Exception</strong> e) {
								e.printStackTrace();
							}
						}
					}.start();
				}
			}
		});
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent <strong>Activity</strong> in <strong>AndroidManifest.xml</strong>.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
</string></string></namevaluepair></namevaluepair>
登录后复制

而下面是一个服务器端php文件(文件内并未连接数据库的操作,如果希望的话,可以连接数据库,获取动态数据。对于php有所了解的人可以很容易的改成连接数据库获取数据的操作)

checkId.php

<?php //获取客户端发送过来的ID和密码
	$id=$_POST[&#39;id&#39;];
	$psw=$_POST[&#39;psw&#39;];

	if($id == "admin" && $psw == "123") {
		$res=array(array());
		$res[0][&#39;userId&#39;]=$id;
		$res[0][&#39;userPsw&#39;]=$psw;

		$res[1][&#39;userId&#39;]="testId1";
		$res[1][&#39;userPsw&#39;]="testPsw1";

		$res[2][&#39;userId&#39;]="testId2";
		$res[2][&#39;userPsw&#39;]="testPsw2";
	}

	echo json_encode($res);
?>
登录后复制


以上就介绍了Android+PHP 使用HttpClient提交POST的请求,使用JSON解析响应,包括了gravity,Apache,Exception,索引,连接数据库方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

关于使用JSF 2.0在命名容器内获取组件clientId的完整前缀的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于@FeignClient注解中属性contextId的使用说明、ajax – 如何处理循环命名容器中的组件、android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2、Android+PHP 使用HttpClient提交POST的请求,使用JSON解析响应的相关信息,请在本站寻找。

本文标签: