搜索词>>Apache Camel 耗时0.0030
  • Spring Boot 2.0 支持的Apache Camel 版本发布了_Apache Camel 2.22发布支持Spring Boot 2.0

    Spring Boot 2.0 支持的Apache Camel 版本发布了_Apache Camel 2.22发布支持Spring Boot 2.0Spring Boot 2.0 支持的Apache Camel 版本发布了_Apache Camel 2.22发布支持Spring Boot 2.0
  • Apache Shiro教程,您的第一个Apache Shiro应用程序(翻译)

    Apache Shiro教程,您的第一个Apache Shiro应用程序(翻译)-编程技术<h2>您的第一个Apache Shiro应用程序</h2> <p>如果你是Apache Shiro的新手,这个简短的教程将告诉你如何设置一个由Apache Shiro保护的初始和非常简单的应用程序。我们将讨论Shiro的核心概念,以帮助您熟悉Shiro的设计和API。</p> <p>如果您不想按照本教程实际编辑文件,则可以获取几乎相同的示例应用程序,并在您参考时进行参考。选择地点:</p> <ul> <li>在Apache Shiro的Git存储库中:https://github.com/apache/shiro/tree/master/samples/quickstart</li> <li>在Apache Shiro的源代码发布的<code>samples/quickstart</code>目录中。源分发可从下载页面获取。</li> </ul> <h3>建立</h3> <p>在这个简单的例子中,我们将创建一个非常简单的命令行应用程序,它将运行并快速退出,这样您可以感受到Shiro的API。</p>  <strong>任何应用程序</strong> <hr /> <p>Apache Shiro是从第一天开始设计的,以支持<em>任何应用</em>程序 - 从最小的命令行应用程序到最大的集群Web应用程序。即使我们为本教程创建了一个简单的应用程序,也知道无论应用程序如何创建或部署在其中,都会使用相同的使用模式。</p> <p>本教程需要Java 1.5或更高版本。我们还将使用Apache Maven作为我们的构建工具,但是当然这不需要使用Apache Shiro。您可以购买Shiro的.jars并以任何你喜欢的方式将它们合并到应用程序中,例如使用Apache Ant和Ivy。</p> <p>对于本教程,请确保您使用的是Maven 2.2.1或更高版本。您应该能够<code>mvn --version</code>在命令提示符中键入,并看到类似于以下内容:</p> <p><strong>测试Maven安装</strong></p> <pre> <code>hazlewood:~/shiro-tutorial$ mvn --version Apache Maven 2.2.1 (r801777; 2009-08-06 12:16:01-0700) Java version: 1.6.0_24 Java home: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home Default locale: en_US, platform encoding: MacRoman OS name: "mac os x" version: "10.6.7" arch: "x86_64" Family: "mac" </code></pre> <p>现在,在文件系统上创建一个新目录,例如,<strong><code>shiro-tutorial</code></strong>并将以下Maven <strong><code>pom.xml</code></strong>文件保存在该目录中:</p> <p><strong>pom.xml</strong></p> <pre> <code class="language-xml"><?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.shiro.tutorials</groupId> <artifactId>shiro-tutorial</artifactId> <version>1.0.0-SNAPSHOT</version> <name>First Apache Shiro Application</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.5</source> <target>1.5</target> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> <!-- This plugin is only to test run our little application. It is not needed in most Shiro-enabled applications: --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.1</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <classpathScope>test</classpathScope> <mainClass>Tutorial</mainClass> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.1.0</version> </dependency> <!-- Shiro uses SLF4J for logging. We'll use the 'simple' binding in this example app. See http://www.slf4j.org for more info. --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.6.1</version> <scope>test</scope> </dependency> </dependencies> </project> </code></pre> <h4>Tutorial类</h4> <p>我们将运行一个简单的命令行应用程序,因此我们需要使用一个<code>public static void main(String[] args)</code>方法创建一个Java类。</p> <p>在包含您的<code>pom.xml</code>文件的同一目录中,创建一个* <code>src/main/java</code>子目录。在<code>src/main/java</code>创建一个<code>Tutorial.java</code>包含以下内容的文件:</p> <p><strong>src / main / java / Tutorial.java</strong></p> <pre> <code class="language-java">import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Tutorial { private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class); public static void main(String[] args) { log.info("My First Apache Shiro Application"); System.exit(0); } } </code></pre> <p>不要担心import语句现在 - 我们会很快得到他们。但是现在,我们有一个典型的命令行程序“shell”。所有这个程序都会打印出文字“我的第一个Apache Shiro应用程序”并退出。</p> <h3>测试运行</h3> <p>要尝试我们的Tutorial应用程序,请在教程项目的根目录(例如<code>shiro-tutorial</code>)中的命令提示符中执行以下命令,然后键入以下内容:</p> <p><code>mvn compile exec:java</code></p> <p>你会看到我们的小教程'应用程序'运行和退出。您应该看到类似以下内容(注意粗体文本,表示我们的输出):</p> <p><strong>运行应用程序</strong></p> <code>lhazlewood:~/projects/shiro-tutorial$ mvn compile exec:java<br /> <br /> ... a bunch of Maven output ...<br /> <br /> <strong>1 [Tutorial.main()] INFO Tutorial - My First Apache Shiro Application</strong><br /> lhazlewood:~/projects/shiro-tutorial\$</code> <p>我们已经验证应用程序运行成功 - 现在让我们启用Apache Shiro。当我们继续教程,你可以运行<code>mvn compile exec:java</code>后,每次我们添加一些更多的代码,以查看我们的更改的结果。</p> <h3>启用S​​hiro</h3> <p>在应用程序中启用Shiro时,首先要了解的是,Shiro中的几乎所有内容都与称为的中央/核心组件相关<code>SecurityManager</code>。对于那些熟悉Java安全性的人,这是Shiro的一个SecurityManager的概念 - 它<em>不是</em>一样的东西<code>java.lang.SecurityManager</code>。</p> <p>虽然我们将在“ 架构”章节中详细介绍Shiro的设计,但现在已经足够了解Shiro <code>SecurityManager</code>是应用程序的Shiro环境的核心,而且每个应用程序<code>SecurityManager</code>都必须存在。因此,我们在Tutorial应用程序中必须做的第一件事是设置<code>SecurityManager</code>实例。</p> <h4>组态</h4> <p>虽然我们可以<code>SecurityManager</code>直接实例化一个类,但是Shiro的<code>SecurityManager</code>实现有足够的配置选项和内部组件,这使得在Java源代码中做这件事变得很困难 - <code>SecurityManager</code>使用灵活的基于文本的配置格式配置更容易。</p> <p>为此,Shiro通过基于文本的INI配置提供了默认的“公分母”解决方案。人们对这些天使用庞大的XML文件感到厌烦,INI很容易阅读,使用简单,而且只需要非常少的依赖。稍后还会看到,通过对对象图形导航的简单理解,INI可以有效地用于配置简单对象图形,如SecurityManager。</p>  <strong>许多配置选项</strong> <hr /> <p>Shiro的<code>SecurityManager</code>实现和所有支持组件都是JavaBeans兼容的。这允许Shiro几乎配置任何配置格式,如XML(Spring,JBoss,Guice等),YAML,JSON,Groovy Builder标记等。INI只是Shiro的“公分母”格式,允许在任何环境中进行配置,以防其他选项不可用。</p>   <h5>shiro.ini</h5> <p>因此,我们将使用一个INI文件来<code>SecurityManager</code>为这个简单的应用程序配置Shiro 。首先,创建一个<strong><code>src/main/resources</code></strong>目录,从同一目录开始,其中<code>pom.xml</code>。然后<code>shiro.ini</code>在该新目录中创建具有以下内容的文件:</p> <p><strong>src / main / resources / shiro.ini</strong></p> <pre> <code># ============================================================================= # Tutorial INI configuration # # Usernames/passwords are based on the classic Mel Brooks' film "Spaceballs" :) # ============================================================================= # ----------------------------------------------------------------------------- # Users and their (optional) assigned roles # username = password, role1, role2, ..., roleN # ----------------------------------------------------------------------------- [users] root = secret, admin guest = guest, guest presidentskroob = 12345, president darkhelmet = ludicrousspeed, darklord, schwartz lonestarr = vespa, goodguy, schwartz # ----------------------------------------------------------------------------- # Roles with assigned permissions # roleName = perm1, perm2, ..., permN # ----------------------------------------------------------------------------- [roles] admin = * schwartz = lightsaber:* goodguy = winnebago:drive:eagle5 </code></pre> <p>正如你所看到的,这个配置基本上设置了一组小的静态用户帐户,足够用于我们的第一个应用程序。在后面的章节中,您将了解如何使用更复杂的用户数据源,如关系数据库,LDAP和ActiveDirectory等。</p> <h4>引用配置</h4> <p>现在我们已经定义了一个INI文件,我们可以<code>SecurityManager</code>在我们的Tutorial应用程序类中创建该实例。更改<code>main</code>方法以反映以下更新:</p> <pre> <code class="language-java">public static void main(String[] args) { log.info("My First Apache Shiro Application"); //1. Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //2. SecurityManager securityManager = factory.getInstance(); //3. SecurityUtils.setSecurityManager(securityManager); System.exit(0); } </code></pre> <p>我们去 - Shiro在我们的示例应用程序中启用,只添加了3行代码!这是多么容易?</p> <p>随意运行<code>mvn compile exec:java</code>,看到一切仍然运行成功(由于Shiro的默认日志记录调试或更低,你不会看到任何Shiro日志消息 - 如果它启动和运行没有错误,那么你知道一切仍然确定)。</p> <p>这里是上面添加的是做什么:</p> <ol> <li> <p>我们使用Shiro的<code>IniSecurityManagerFactory</code>实现来获取<code>shiro.ini</code>位于类路径根目录的文件。这个实现反映了Shiro对工厂方法设计模式的支持。该<code>classpath:</code>前缀是一个资源的指标,告诉四郎在哪里加载从ini文件(其它前缀,如<code>url:</code>和<code>file:</code>以及支持)。</p> </li> <li> <p>该<code>factory.getInstance()</code>方法被调用,它解析INI文件并返回一个<code>SecurityManager</code>反映配置的实例。</p> </li> <li> <p>在这个简单的示例中,我们将其设置<code>SecurityManager</code>为<em>静态</em>(内存)单例,可通过JVM访问。但请注意,如果您在单个JVM中将有多个启用Shiro的应用程序,这是不可取的。对于这个简单的例子,它是确定,但更复杂的应用程序环境通常会放置<code>SecurityManager</code>在应用程序特定的内存(如在Web应用程序<code>ServletContext</code>或Spring,Guice或JBoss DI容器实例)。</p> </li> </ol> <h3>使用Shiro</h3> <p>现在我们的SecurityManager已经设置好了,现在我们可以开始做我们真正关心的事情 - 执行安全操作。</p> <p>当保护我们的应用程序时,我们可能最相关的问题是“当前用户是谁”或“当前用户是否允许做X”?在我们编写代码或设计用户界面时,常常会提出这些问题:应用程序通常基于用户故事构建,并且您希望基于每个用户表示(和安全)的功能。因此,我们在应用程序中考虑安全性的最自然的方式是基于当前用户。Shiro的API从根本上代表了“当前用户”的<code>Subject</code>概念。</p> <p>在几乎所有环境中,您可以通过以下调用获取当前正在执行的用户:</p> <pre> <code>Subject currentUser = SecurityUtils.getSubject(); </code></pre> <p>使用<code>SecurityUtils</code>。getSubject(),我们可以获取当前正在执行的<code>Subject</code>。<em>主题</em>是一个安全术语,基本上意味着“当前正在执行的用户的安全特定视图”。它不被称为“用户”,因为“用户”这个词通常与一个人相关联。在安全世界中,术语“主题”可以指人,也可以是第三方进程,cron作业,守护进程帐户或任何类似的。它只是指“当前与软件交互的东西”。对于大多数意图和目的,你可以认为<code>Subject</code>是Shiro的'用户'概念。</p> <p>独立应用程序中的<code>getSubject()</code>调用可以<code>Subject</code>基于应用程序特定位置中的用户数据返回,并且在服务器环境(例如web应用程序)中,它<code>Subject</code>基于与当前线程或传入请求相关联的用户数据来获取。</p> <p>现在你有了<code>Subject</code>,你能用它做什么?</p> <p>如果您想在用户在应用程序的当前会话期间使用户可用,您可以获取其会话:</p> <pre> <code>Session session = currentUser.getSession(); session.setAttribute( "someKey", "aValue" ); </code></pre> <p>这<code>Session</code>是一个Shiro特定的实例,提供了大多数你习惯了与常规HttpSessions,但有一些额外的好处和一个<strong>巨大的</strong>区别:它不需要HTTP环境!</p> <p>如果在Web应用程序中部署,默认情况下<code>Session</code>将<code>HttpSession</code>基于。但是,在非Web环境中,像这个简单的教程应用程序,Shiro将默认自动使用其企业会话管理。这意味着您可以在任何层次的应用程序中使用相同的API,而不考虑部署环境!这打开了一个全新的应用程序世界,因为任何需要会话的应用程序不需要被强制使用<code>HttpSession</code>或EJB有状态会话Bean。而且,任何客户端技术现在都可以共享会话数据。</p> <p>所以现在你可以获得一个<code>Subject</code>和他们<code>Session</code>。怎么样<em>真正</em>像检查,如果他们被允许做的事情,比如对角色和权限检查有用的东西?</p> <p>好吧,我们只能为已知用户执行这些检查。我们的<code>Subject</code>上面的实例代表当前用户,但<em>谁</em>是当前用户?好吧,他们是匿名的 - 也就是说,直到他们至少登录一次。所以,让我们这样做:</p> <pre> <code class="language-java">if ( !currentUser.isAuthenticated() ) { //collect user principals and credentials in a gui specific manner //such as username/password html form, X509 certificate, OpenID, etc. //We'll use the username/password example here since it is the most common. UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); //this is all you have to do to support 'remember me' (no config - built in!): token.setRememberMe(true); currentUser.login(token); } </code></pre> <p>而已!这不容易。</p> <p>但是,如果他们的登录尝试失败怎么办?您可以捕获各种特定的异常,告诉您发生了什么,并允许您处理并做出相应的反应:</p> <pre> <code class="language-java">try { currentUser.login( token ); //if no exception, that's it, we're done! } catch ( UnknownAccountException uae ) { //username wasn't in the system, show them an error message? } catch ( IncorrectCredentialsException ice ) { //password didn't match, try again? } catch ( LockedAccountException lae ) { //account for that username is locked - can't login. Show them a message? } ... more types exceptions to check if you want ... } catch ( AuthenticationException ae ) { //unexpected condition - error? } </code></pre> <p>有很多不同类型的异常,你可以检查,或抛出自己的自定义条件Shiro可能不考虑。有关更多信息,请参阅AuthenticationException JavaDoc。</p>  <strong>方便的提示</strong> <hr /> <p>安全最佳做法是向用户提供通用登录失败消息,因为您不想帮助攻击者试图进入您的系统。</p> <p>好的,所以到现在为止,我们有一个登录用户。我们还能做什么?</p> <p>让我们说他们是谁:</p> <pre> <code>//print their identifying principal (in this case, a username): log.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." ); </code></pre> <p>我们还可以测试他们是否有特定的作用:</p> <pre> <code class="language-java">if ( currentUser.hasRole( "schwartz" ) ) { log.info("May the Schwartz be with you!" ); } else { log.info( "Hello, mere mortal." ); } </code></pre> <p>我们还可以看到他们是否有权对某种类型的实体采取行动:</p> <pre> <code class="language-java">if ( currentUser.isPermitted( "lightsaber:weild" ) ) { log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } </code></pre> <p>此外,我们可以执行非常强大的<em>实例级</em>权限检查 - 查看用户是否能够访问类型的特定实例:</p> <pre> <code class="language-java">if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) { log.info("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " + "Here are the keys - have fun!"); } else { log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); } </code></pre> <p>蛋糕,对吧?</p> <p>最后,当用户完成使用应用程序时,他们可以注销:</p> <pre> <code>currentUser.logout(); //removes all identifying information and invalidates their session too. </code></pre> <h4>最终教程类</h4> <p>在添加上面的代码示例之后,这里是我们最终的Tutorial类文件。随意编辑和玩它,并更改安全检查(和INI配置),你喜欢:</p> <p><strong>最终src / main / java / Tutorial.java</strong></p> <pre> <code class="language-java">import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Tutorial { private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class); public static void main(String[] args) { log.info("My First Apache Shiro Application"); Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); // get the currently executing user: Subject currentUser = SecurityUtils.getSubject(); // Do some stuff with a Session (no need for a web or EJB container!!!) Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Retrieved the correct value! [" + value + "]"); } // let's login the current user so we can check against roles and permissions: if (!currentUser.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true); try { currentUser.login(token); } catch (UnknownAccountException uae) { log.info("There is no user with username of " + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { log.info("Password for account " + token.getPrincipal() + " was incorrect!"); } catch (LockedAccountException lae) { log.info("The account for username " + token.getPrincipal() + " is locked. " + "Please contact your administrator to unlock it."); } // ... catch more exceptions here (maybe custom ones specific to your application? catch (AuthenticationException ae) { //unexpected condition? error? } } //say who they are: //print their identifying principal (in this case, a username): log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //test a role: if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //test a typed permission (not instance-level) if (currentUser.isPermitted("lightsaber:weild")) { log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } //a (very powerful) Instance Level permission: if (currentUser.isPermitted("winnebago:drive:eagle5")) { log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " + "Here are the keys - have fun!"); } else { log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); } //all done - log out! currentUser.logout(); System.exit(0); } } </code></pre> <h3>概要</h3> <p>希望这个介绍教程帮助你了解如何设置Shiro在一个基本的应用程序,以及Shiro的主要设计概念,<code>Subject</code>和<code>SecurityManager</code>。</p> <p>但这是一个相当简单的应用程序。你可能会问自己,“如果我不想使用INI用户帐户而是想连接到更复杂的用户数据源怎么办?</p> <p>要回答这个问题,需要更深入地了解Shiro的架构和支持配置机制。接下来我们将介绍Shiro的建筑。</p>
  • java编程中采用Apache common.httpclient方式模拟POST请求

    java编程中采用Apache common.httpclient方式模拟POST请求java编程中采用Apache common.httpclient方式模拟POST请求 <pre> <code class="language-java">import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; public class HttpclientUtils { /** * 采用Apache common.httpclient方式模拟POST请求 * * @param url * @param params * @return * @throws HttpException * @throws IOException */ public static String doPost(String url, Map<String, String> params) throws HttpException, IOException { HttpClient client = new HttpClient(); PostMethod method = new PostMethod(url); client.getParams().setContentCharset("UTF-8"); method.setRequestHeader("ContentType", "application/x-www-form-urlencoded;charset=UTF-8"); List<NameValuePair> dataList = new ArrayList<>(); if (params != null && !params.isEmpty()) { for (Map.Entry<String, String> entry : params.entrySet()) { dataList.add(new NameValuePair(entry.getKey(), entry.getValue())); } } if (!dataList.isEmpty()) { method.setRequestBody(dataList.toArray(new NameValuePair[0])); } client.executeMethod(method); String SubmitResult = method.getResponseBodyAsString(); return SubmitResult; } } </code></pre>
  • Apache配置worker模式_Apache配置worker模式调优

    Apache配置worker模式_Apache配置worker模式调优1.通过yum安装Apache(安装版本为:2.4.6)<br /> <br /> 2.查看默认的工作模式 <pre> <code class="language-html">[root@VM_26_67_centos ~]# httpd -V AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message Server version: Apache/2.4.6 (CentOS) Server built:   Oct 19 2017 20:39:16 Server's Module Magic Number: 20120211:24 Server loaded:  APR 1.4.8, APR-UTIL 1.5.2 Compiled using: APR 1.4.8, APR-UTIL 1.5.2 Architecture:   64-bit Server MPM:     prefork   threaded:     no     forked:     yes (variable process count) Server compiled with....  -D APR_HAS_SENDFILE  -D APR_HAS_MMAP  -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)  -D APR_USE_SYSVSEM_SERIALIZE  -D APR_USE_PTHREAD_SERIALIZE  -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT  -D APR_HAS_OTHER_CHILD  -D AP_HAVE_RELIABLE_PIPED_LOGS  -D DYNAMIC_MODULE_LIMIT=256  -D HTTPD_ROOT="/etc/httpd"  -D SUEXEC_BIN="/usr/sbin/suexec"  -D DEFAULT_PIDLOG="/run/httpd/httpd.pid"  -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"  -D DEFAULT_ERRORLOG="logs/error_log"  -D AP_TYPES_CONFIG_FILE="conf/mime.types</code></pre> <br /> 3.切换到Apache的配置目录 <pre> <code class="language-html">#cd /etc/httpd/</code></pre> <br /> 这里有三个配置目录<br /> conf->核心配置<br /> conf.d->在conf中的http.conf会引入该目录下的其他配置<br /> conf.modules.d->Apache 的模块配置<br /> <br /> 还有个模块的安装存放目录的链接目录<br /> modules->模块存放目录<br /> 查看安装的工作模式模块 <pre> <code class="language-html">[root@VM_26_67_centos httpd]# ll modules/mod_mpm_* -rwxr-xr-x 1 root root 61040 Oct 20 04:40 modules/mod_mpm_event.so -rwxr-xr-x 1 root root 31872 Oct 20 04:40 modules/mod_mpm_prefork.so -rwxr-xr-x 1 root root 48520 Oct 20 04:40 modules/mod_mpm_worker.so [root@VM_26_67_centos httpd]# </code></pre> <br /> 4.修改加载模式模块<br /> 切换至模块加载配置文件目录 <pre> <code class="language-html">[root@VM_26_67_centos httpd]# cd /etc/httpd/conf.modules.d/ [root@VM_26_67_centos conf.modules.d]# ls 00-base.conf  00-dav.conf  00-lua.conf  00-mpm.conf  00-proxy.conf  00-systemd.conf  01-cgi.conf  10-php.conf [root@VM_26_67_centos conf.modules.d]#</code></pre> <br /> 修改配置文件00-mpm.conf <pre> <code class="language-bash"># Select the MPM module which should be used by uncommenting exactly # one of the following LoadModule lines: # prefork MPM: Implements a non-threaded, pre-forking web server # See: http://httpd.apache.org/docs/2.4/mod/prefork.html #注释默认工作模式模块 #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # worker MPM: Multi-Processing Module implementing a hybrid # multi-threaded multi-process web server # See: http://httpd.apache.org/docs/2.4/mod/worker.html #启用worker工作模式模块 LoadModule mpm_worker_module modules/mod_mpm_worker.so # event MPM: A variant of the worker MPM with the goal of consuming # threads only for connections with active processing # See: http://httpd.apache.org/docs/2.4/mod/event.html # #LoadModule mpm_event_module modules/mod_mpm_event.so </code></pre> <br /> <br /> 5.在Apache得核心配置文件httpd.conf中添加以下配置模块 <pre> <code class="language-html">cd /etc/httpd/conf <IfModule mpm_worker_module>     StartServers             3     MinSpareThreads         75     MaxSpareThreads        250     ThreadsPerChild         25     MaxRequestWorkers      400     MaxConnectionsPerChild   0 </IfModule></code></pre> 建议配置: <pre> <code class="language-bash">#mpm_worker模块 <IfModule mpm_worker_module> StartServers 2 #推荐设置:小=默认 中=3~5 大=5~10 MaxClients 150 #推荐设置:小=500 中=500~1500 大型=1500~3000 MinSpareThreads 25 #推荐设置:小=默认 中=50~100 大=100~200 MaxSpareThreads 75 #推荐设置:小=默认 中=80~160 大=200~400 ThreadsPerChild 25 #推荐设置:小=默认 中=50~100 大型=100~200 MaxRequestsPerChild 0 #推荐设置:小=10000 中或大=10000~50000 #(此外,如果MaxClients/ThreadsPerChild大于16,还需额外设置ServerLimit参数,ServerLimit必须大于等于 MaxClients/ThreadsPerChild 的值。) </IfModule></code></pre> <p>对应的配置参数作用如下:</p> StartServers<br /> 启动Apache时创建的子进程数。<br /> MinSpareServers<br /> 处于空闲状态的最小子进程数。 <p>所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于<code>MinSpareServers</code>,那么Apache将以最大每秒一个的速度产生新的子进程。只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。</p> <br /> MaxSpareServers<br /> 处于空闲状态的最大子进程数。 <p>只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。如果你将该指令的值设置为比<code>MinSpareServers</code>小,Apache将会自动将其修改成<code>MinSpareServers+1</code>。</p> <br /> MaxClients<br /> 允许同时连接的最大请求数量。 <p>任何超过<code>MaxClients</code>限制的请求都将进入等待队列,直到达到<code>ListenBacklog</code>指令限制的最大值为止。</p> <p>对于非线程型的MPM(也就是<code>mpm_prefork</code>),<code>MaxClients</code>表示可以用于处理客户端请求的最大子进程数量,默认值是256。要增大这个值,你必须同时增大<code>ServerLimit</code>。</p> <p>对于线程型或者混合型的MPM(也就是<code>mpm_beos</code>或<code>mpm_worker</code>),<code>MaxClients</code>表示可以用于处理客户端请求的最大线程数量。线程型的<code>mpm_beos</code>的默认值是50。对于混合型的MPM默认值是16(<code>ServerLimit</code>)乘以25(<code>ThreadsPerChild</code>)的结果。因此要将<code>MaxClients</code>增加到超过16个进程才能提供的时候,你必须同时增加<code>ServerLimit</code>的值。</p> <br /> MinSpareThreads<br /> 处于空闲状态的最小线程数。 <p>不同的MPM对这个指令的处理是不一样的:</p> <p><code>mpm_worker</code>的默认值是75。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。<code>mpm_netware</code>的默认值是10。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。<code>mpm_beos</code>和<code>mpmt_os2</code>的工作方式与<code>mpm_netware</code>差不多,<code>mpm_beos</code>的默认值是1;<code>mpmt_os2</code>的默认值是5。</p> <br /> MaxSpareThreads<br /> 处于空闲状态的最大线程数。 <p>不同的MPM对这个指令的处理是不一样的:</p> <p><code>mpm_worker</code>的默认值是250。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。<code>mpm_netware</code>的默认值是100。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。<code>mpm_beos</code>和<code>mpmt_os2</code>的工作方式与<code>mpm_netware</code>差不多,<code>mpm_beos</code>的默认值是50;<code>mpmt_os2</code>的默认值是10。</p> <p><em>备注</em>:<code>ServerLimit</code>表示Apache允许创建的最大进程数。 值得注意的是,Apache在编译时内部有一个硬限制<code>ServerLimit 20000</code>(对于<code>mpm_prefork</code>模块为<code>ServerLimit 200000</code>)。你不能超越这个限制。<br /> 使用这个指令时要特别当心。如果将<code>ServerLimit</code>设置成一个高出实际需要许多的值,将会有过多的共享内存被分配。如果将<code>ServerLimit</code>和<code>MaxClients</code>设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。</p> <p><em>注意</em>:在配置相关参数时,请先保证服务器具备<em>足够</em>的硬件性能(例如:CPU、内存等)。 如果发现自启动后,随着服务器的运行时间增加,服务器的内存占用也随之增加,可能是程序中出现内存泄露,请向下调整参数<code>MaxRequestsPerChild</code>的值以降低内存泄露带来的影响,然后尽快找出程序中的问题之所在。</p> <br /> 6.重启httpd服务 <pre> <code class="language-html">[root@VM_26_67_centos httpd]# service httpd restart</code></pre> <br /> <br /> 7.查看工作模式 <pre> <code class="language-html">[root@VM_26_67_centos httpd]# httpd -V AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message Server version: Apache/2.4.6 (CentOS) Server built:   Oct 19 2017 20:39:16 Server's Module Magic Number: 20120211:24 Server loaded:  APR 1.4.8, APR-UTIL 1.5.2 Compiled using: APR 1.4.8, APR-UTIL 1.5.2 Architecture:   64-bit Server MPM:     worker   threaded:     yes (fixed thread count)     forked:     yes (variable process count) Server compiled with....  -D APR_HAS_SENDFILE  -D APR_HAS_MMAP  -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)  -D APR_USE_SYSVSEM_SERIALIZE  -D APR_USE_PTHREAD_SERIALIZE  -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT  -D APR_HAS_OTHER_CHILD  -D AP_HAVE_RELIABLE_PIPED_LOGS  -D DYNAMIC_MODULE_LIMIT=256  -D HTTPD_ROOT="/etc/httpd"  -D SUEXEC_BIN="/usr/sbin/suexec"  -D DEFAULT_PIDLOG="/run/httpd/httpd.pid"  -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"  -D DEFAULT_ERRORLOG="logs/error_log"  -D AP_TYPES_CONFIG_FILE="conf/mime.types"  -D SERVER_CONFIG_FILE="conf/httpd.conf"</code></pre>
  • apache 24 配置301跳转 解决cdn问题

    apache 24 配置301跳转 解决cdn问题<IfModule rewrite_module> Options +FollowSymLinks RewriteEngine on RewriteCond Host: ^localhost$ #RedirectMatch 301 /static/(.*) http\://cdn\.icdicn\.com/static/$1 RedirectMatch 301 /static/img/(.*) http\://cdn\.icdicn\.com/static/img/$1 RedirectMatch 301 /static/echarts\.min\.js http\://cdn\.icdicn\.com/static/echarts\.min\.js RedirectMatch 301 /static/public-framework\.js http\://cdn\.icdicn\.com/static/public-framework\.js </IfModule>​​​​​​​代码段 小部件
  • Java 10上的Apache CXF

    Java 10上的Apache CXFNginx 启动、停止、重启启动命令:#nginx停止命令:nginx -s stop​​​​​​​代码段 小部件
  • Apache ab压力测试摘记

    Apache ab压力测试摘记命令:ab -n 800 -c 800 http://192.168.0.10/ 说明:(-n发出800个请求,-c模拟800并发,相当800人同时访问,后面是测试url)命令:ab -t 60 -c 100 http://192.168.0.10/ 说明:在60秒内发请求,一次100个请求。命令:ab -t 60 -c 100 -T "text/plain" -p p.txt http://192.168.0.10/hello.html 说明:如果需要在url中带参数p.txt 是和ab.exe在一个目录 p.txt 中可以写参数,如 p=wdp&fq=78结果参数解释This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.0.10 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Finished 800 requests Server Software: Microsoft-HTTPAPI/2.0 Server Hostname: 192.168.0.10 Server Port: 80 Document Path: / Document Length: 315 bytes HTTP响应数据的正文长度 Concurrency Level: 800 Time taken for tests: 0.914 seconds 所有这些请求处理完成所花费的时间 Complete requests: 800 完成请求数 Failed requests: 0 失败请求数 Write errors: 0 Non-2xx responses: 800 Total transferred: 393600 bytes 网络总传输量 HTML transferred: 252000 bytes HTML内容传输量 Requests per second: 875.22 [#/sec] (mean) 吞吐量-每秒请求数 Time per request: 914.052 [ms] (mean) 服务器收到请求,响应页面要花费的时间 Time per request: 1.143 [ms] (mean, across all concurrent requests) 并发的每个请求平均消耗时间 Transfer rate: 420.52 [Kbytes/sec] received 平均每秒网络上的流量,可以帮助排除是否存在网络流量过大导致响应时间延长的问题 网络上消耗的时间的分解: Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 0.5 1 3 Processing: 245 534 125.2 570 682 Waiting: 11 386 189.1 409 669 Total: 246 535 125.0 571 684 整个场景中所有请求的响应情况。在场景中每个请求都有一个响应时间 其中 50% 的用户响应时间小于 571 毫秒 80 % 的用户响应时间小于 652 毫秒 最大的响应时间小于 684 毫秒 Percentage of the requests served within a certain time (ms) 50% 571 66% 627 75% 646 80% 652 90% 666 95% 677 98% 681 99% 682 100% 684 (longest request)
  • Java编程之Apache Shiro Web支持

    组态,将Shiro集成到任何Web应用程序中的最简单的方法是在web.xml中配置Servlet ContextListener和Filter,了解如何读取Shiro的INI配置。<h1>组态</h1> <p>将Shiro集成到任何Web应用程序中的最简单的方法是在web.xml中配置Servlet ContextListener和Filter,了解如何读取Shiro的INI配置。大部分INI配置格式本身在配置页面的INI Sections部分中定义,但我们将在此处介绍一些其他特定于Web的部分。</p>  <strong>使用Spring?</strong> <hr /> <p>Spring Framework用户不会执行此设置。如果你使用Spring,你将需要阅读关于Spring特定的web配置。</p>   <h3>web.xml</h3> <h4>Shiro 1.2以后</h4> <p>在Shiro 1.2及更高版本中,标准Web应用程序通过添加以下XML块来初始化Shiro <code>web.xml</code>:</p> <pre> <code class="language-xml"><listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> ... <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping> </code></pre> <p>这假设一个Shiro INI 配置文件位于以下两个位置之一,使用以前找到的位置:</p> <ol> <li><code>/WEB-INF/shiro.ini</code></li> <li><code>shiro.ini</code> 文件在类路径的根。</li> </ol> <p>这里是上面的配置:</p> <ul> <li> <p>的<code>EnvironmentLoaderListener</code>初始化四郎<code>WebEnvironment</code>实例(包含一切四郎需要操作,包括<code>SecurityManager</code>),并使其在访问<code>ServletContext</code>。如果您需要随时获取此<code>WebEnvironment</code>实例,则可以调用<code>WebUtils.getRequiredWebEnvironment(servletContext)</code>。</p> </li> <li> <p>该<code>ShiroFilter</code>会利用这个<code>WebEnvironment</code>来执行所有必要的安全操作的任何过滤的要求。</p> </li> <li> <p>最后,该<code>filter-mapping</code>定义确保所有请求都被过滤<code>ShiroFilter</code>,建议大多数Web应用程序使用,以确保任何请求都是安全的。</p> </li> </ul>  <strong>ShiroFilter过滤器映射</strong> <hr /> <p>通常希望在任何其他“filter-mapping”声明之前定义“ShiroFilter filter-mapping”,以确保Shiro也能在这些过滤器中运行。</p>   <h5>自定义<code>WebEnvironment</code>类</h5> <p>默认情况下,<code>EnvironmentLoaderListener</code>将创建一个<code>IniWebEnvironment</code>实例,它承担Shiro的基于INI的配置。如果愿意,您可以<code>WebEnvironment</code>通过在<code>ServletContext</code> <code>context-param</code>中指定一个自定义实例来指定<code>web.xml</code>:</p> <pre> <code class="language-xml"><context-param> <param-name>shiroEnvironmentClass</param-name> <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value> </context-param> </code></pre> <p>这允许您自定义如何解析配置格式并将其表示为<code>WebEnvironment</code>实例。您可以对现有<code>IniWebEnvironment</code>的自定义行为进行子类化,或者完全支持不同的配置格式。例如,如果有人想要在XML而不是INI中配置Shiro,他们可以创建一个基于XML的实现,例如<code>com.foo.bar.shiro.XmlWebEnvironment</code>。</p> <h5>自定义配置位置</h5> <p>本<code>IniWebEnvironment</code>类希望读取并加载INI配置文件。默认情况下,此类将自动查找以下两个位置的Shiro <code>.ini</code>配置(按顺序):</p> <ol> <li><code>/WEB-INF/shiro.ini</code></li> <li><code>classpath:shiro.ini</code></li> </ol> <p>它将使用先找到的。</p> <p>然而,如果你希望将你的配置在其他位置,则可能与另一指定位置<code>context-param</code>在<code>web.xml</code>:</p> <pre> <code class="language-xml"><context-param> <param-name>shiroConfigLocations</param-name> <param-value>YOUR_RESOURCE_LOCATION_HERE</param-value> </context-param> </code></pre> <p>默认情况下,<code>param-value</code>期望由<code>ServletContext.getResource</code>方法定义的规则可解析。例如,<code>/WEB-INF/some/path/shiro.ini</code></p> <p>但是,您也可以使用Shiro的ResourceUtils类支持的适当资源前缀来指定特定的文件系统,类路径或URL位置,例如:</p> <ul> <li><code>file:/home/foobar/myapp/shiro.ini</code></li> <li><code>classpath:com/foo/bar/shiro.ini</code></li> <li><code>url:http://confighost.mycompany.com/myapp/shiro.ini</code></li> </ul> <h4>Shiro 1.1和更早版本</h4> <p>在1.1或更早版本的Web应用程序中启用Shiro的最简单的方法是定义IniShiroFilter并指定<code>filter-mapping</code>:</p> <pre> <code class="language-xml"><filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class> </filter> ... <!-- Make sure any request you want accessible to Shiro is filtered. /* catches all --> <!-- requests. Usually this filter mapping is defined first (before all others) to --> <!-- ensure that Shiro works in subsequent filters in the filter chain: --> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping> </code></pre> <p>此定义要求您的INI配置位于类路径(例如<code>classpath:shiro.ini</code>)的根目录下的shiro.ini文件中。</p> <h5>自定义路径</h5> <p>如果不想将INI配置放入<code>/WEB-INF/shiro.ini</code>或<code>classpath:shiro.ini</code>,您可以根据需要指定自定义资源位置。添加<code>configPath init-param</code>并指定资源位置:</p> <pre> <code class="language-xml"><filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class> <init-param> <param-name>configPath</param-name> <param-value>/WEB-INF/anotherFile.ini</param-value> </init-param> </filter> ... </code></pre> <p>未限定(无限额或“非前缀”)<code>configPath</code>值被假定为<code>ServletContext</code>资源路径,可通过该<br /> <code>ServletContext.getResource</code>方法定义的规则解析。</p>  <strong>ServletContext资源路径 - Shiro 1.2+</strong> <hr /> <p>ServletContext资源路径在Shiro 1.2和更高版本中可用。在1.1和更早的版本中,所有<code>configPath</code>的定义必须指定<code>classpath:</code>,<code>file:</code>或<code>url:</code>前缀。</p> <p>你也可以指定其他非<code>ServletContext</code>使用资源位置<code>classpath:</code>,<code>url:</code>或<code>file:</code>前缀分别表示classpath中,URL或文件系统位置。例如:</p> <pre> <code class="language-xml">... <init-param> <param-name>configPath</param-name> <param-value>url:http://configHost/myApp/shiro.ini</param-value> </init-param> ... </code></pre> <h5>内联配置</h5> <p>最后,还可以将INI配置嵌入到web.xml中,而不使用INI文件。您可以使用<code>config init-param</code>而不是<code>configPath</code>:</p> <pre> <code class="language-xml"><filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class> <init-param><param-name>config</param-name><param-value> # INI Config Here </param-value></init-param> </filter> ... </code></pre> <p>直列配置往往细小型或简单的应用,但它通常是更方便的外部化它的原因如下专用shiro.ini文件:</p> <ul> <li>您可以编辑安全配置很多,并且不想将修订控制'noise'添加到web.xml文件</li> <li>您可能希望将安全配置与web.xml配置的其余部分分离</li> <li>您的安全配置可能会变大,您希望保持web.xml精简并更易于阅读</li> <li>你有一个复杂的构建系统,其中相同的shiro配置可能需要在多个地方引用</li> </ul> <p>这取决于你 - 使用什么对你的项目有意义。</p> <h3>Web INI配置</h3> <p>除了标准<code>[main]</code>,<code>[users]</code>并<code>[roles]</code>在主已经说明部分配置章节中,你还可以指定一个特定的网络<code>[urls]</code>在部分<code>shiro.ini</code>文件:</p> <pre> <code># [main], [users] and [roles] above here ... [urls] ... </code></pre> <p>该<code>[urls]</code>部分允许你做一些事情,不以任何Web框架存在,我们见过的:确定特设的过滤器链在应用程序中任何匹配的URL路径的能力!</p> <p>这是<em>远远</em>比你通常定义过滤链更灵活,功能强大,简洁的<code>web.xml</code>:即使你从未使用过任何其他的功能,该功能提供四郎也只有这个使用,仅此一项就使值得使用。</p> <h4>[urls]</h4> <p>该<code>urls</code>节中每行的格式如下:</p> <pre> <code>_URL_Ant_Path_Expression_ = _Path_Specific_Filter_Chain_ </code></pre> <p>例如:</p> <pre> <code>... [urls] /index.html = anon /user/create = anon /user/** = authc /admin/** = authc, roles[administrator] /rest/** = authc, rest /remoting/rpc/** = authc, perms["remote:invoke"] </code></pre> <p>接下来,我们将详细介绍这些行的含义。</p> <p>等号(=)左侧的令牌是相对于Web应用程序的上下文根的Ant样式路径表达式。</p> <p>例如,假设您有以下<code>[urls]</code>行:</p> <pre> <code>/account/** = ssl, authc </code></pre> <p>该行指出:“以我的应用程序的路径的任何请求<code>/account</code>或任何它的子路径(<code>/account/foo</code>,<code>/account/bar/baz</code>,等),将触发”SSL,authc'过滤器链“。我们将在下面介绍过滤链。</p> <p>请注意,所有路径表达式都与应用程序的上下文根相关。这意味着如果你部署你的应用程序一天,<code>www.somehost.com/myapp</code>然后,然后将其部署到<code>www.anotherhost.com</code>(没有'myapp'子路径),模式匹配仍然会工作。所有路径都是相对于HttpServletRequest.getContextPath()值。</p>  <strong>订单事项!</strong> <hr /> <p>URL路径表达式根据传入请求按照它们定义的顺序和<em>第一个匹配的WINS</em>进行评估。例如,让我们假设有以下链定义:</p> <pre> <code>/account/** = ssl, authc /account/signup = anon </code></pre> <p>如果传入的请求打算到达<code>/account/signup/index.html</code>(所有“anon'ymous用户可访问),<em>它将永远不会被处理!</em>。原因是该<code>/account/**</code>模式首先匹配传入请求,并将所有剩余定义“短路”。</p> <p>始终记住根据<em>FIRST MATCH WINS</em>策略定义您的过滤器链!</p> <p> </p>   <h5>过滤器链定义</h5> <p>等号(=)右侧的令牌是以逗号分隔的过滤器列表,以对匹配该路径的请求执行。它必须匹配以下格式:</p> <pre> <code>filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN] </code></pre> <p>哪里:</p> <ul> <li><em>filterN</em>是在<code>[main]</code>部分中定义的过滤器bean的名称</li> <li><code>[optional_configN]</code>是一个可选的括号字符串,对于<em>该特定路径</em>(每个过滤器,<em>特定</em>于<em>路径的</em>配置!)<em>的特定</em>过滤器具有含义。如果过滤器不需要为该URL路径指定特定的配置,您可以丢弃括号,<code>filterN[]</code>只是变成了<code>filterN</code>。</li> </ul> <p>并且因为过滤器令牌定义链(aka List),记住顺序很重要!按您希望请求流过链的顺序定义逗号分隔的列表。</p> <p>最后,如果不满足其必要条件(例如,执行重定向,使用HTTP错误代码进行响应,直接呈现等),则每个过滤器都可以自由地处理响应。否则,预期允许请求通过链继续到最终目的地视图。</p>  <strong>小费</strong> <hr /> <p>能够对路径特定配置(即<code>[optional_configN]</code>过滤器令牌的一部分)做出反应是对于Shiro过滤器可用的独特特征。</p> <p>如果你想创建自己的<code>javax.servlet.Filter</code>实现,也可以这样做,请确保你的过滤器子类org.apache.shiro.web.filter.PathMatchingFilter</p> <p> </p>   <h6>可用过滤器</h6> <p>可用于过滤器链定义的“池”过滤器在此<code>[main]</code>部分中定义。在主节中分配给它们的名称是在过滤器链定义中使用的名称。例如:</p> <pre> <code>[main] ... myFilter = com.company.web.some.FilterImplementation myFilter.property1 = value1 ... [urls] ... /some/path/** = myFilter </code></pre> <h2>默认过滤器</h2> <p>当运行Web应用程序时,Shiro将创建一些有用的默认<code>Filter</code>实例,并使其在<code>[main]</code>部分自动可用。您可以像配置<code>main</code>其他bean一样配置它们,并在链定义中引用它们。例如:</p> <pre> <code>[main] ... # Notice how we didn't define the class for the FormAuthenticationFilter ('authc') - it is instantiated and available already: authc.loginUrl = /login.jsp ... [urls] ... # make sure the end-user is authenticated. If not, redirect to the 'authc.loginUrl' above, # and after successful authentication, redirect them back to the original account page they # were trying to view: /account/** = authc ... </code></pre> <p>自动可用的默认Filter实例由DefaultFilter枚举定义,枚举的<code>name</code>字段是可用于配置的名称。他们是:</p> <table> <thead> <tr> <th>过滤器名称</th> <th>类</th> </tr> </thead> <tbody> <tr> <td>anon</td> <td>org.apache.shiro.web.filter.authc.AnonymousFilter</td> </tr> <tr> <td>authc</td> <td>org.apache.shiro.web.filter.authc.FormAuthenticationFilter</td> </tr> <tr> <td>authcBasic</td> <td>org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter</td> </tr> <tr> <td>登出</td> <td>org.apache.shiro.web.filter.authc.LogoutFilter</td> </tr> <tr> <td>noSessionCreation</td> <td>org.apache.shiro.web.filter.session.NoSessionCreationFilter</td> </tr> <tr> <td>烫发</td> <td>org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter</td> </tr> <tr> <td>港口</td> <td>org.apache.shiro.web.filter.authz.PortFilter</td> </tr> <tr> <td>休息</td> <td>org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter</td> </tr> <tr> <td>角色</td> <td>org.apache.shiro.web.filter.authz.RolesAuthorizationFilter</td> </tr> <tr> <td>ssl</td> <td>org.apache.shiro.web.filter.authz.SslFilter</td> </tr> <tr> <td>用户</td> <td>org.apache.shiro.web.filter.authc.UserFilter</td> </tr> </tbody> </table> <h2>启用和禁用过滤器</h2> <p>与任何过滤器链定义机制(<code>web.xml</code>,Shiro的INI等)的情况一样,只需通过将过滤器包含在过滤器链定义中来启用它,并通过从链定义中删除它来禁用它。</p> <p>但是在Shiro 1.2中添加的一个新功能是能够启用或禁用过滤器,而不从过滤器链中删除它们。如果启用(默认设置),则会按预期对请求进行过滤。如果禁用,则过滤器将允许请求立即传递到中的下一个元素<code>FilterChain</code>。您可以通常基于配置属性触发过滤器的启用状态,或者甚至可以<em>根据请求</em>触发它。</p> <p>这是一个强大的概念,因为与更改静态过滤器链定义(这将是永久和不灵活的)相比,基于某些要求启用或禁用过滤器通常更方便。</p> <p>Shiro通过其OncePerRequestFilter抽象父类完成此操作。所有Shiro的开箱即用的Filter实现子类化这一个,因此可以启用或禁用,而不从过滤器链中删除它们。你可以为你自己的过滤器实现子类这个类,如果你也需要这个功能*。</p> <p>* SHIRO-224希望能为任何过滤器启用此功能,而不只是那些子类<code>OncePerRequestFilter</code>。如果这对您很重要,请投票支持此问题。</p> <h3>一般启用/禁用</h3> <p>该OncePerRequestFilter(及其所有子类)支持启用/所有的请求,以及在每个请求的基础禁用。</p> <p>对所有请求的一般启用或禁用过滤器是通过将其<code>enabled</code>属性设置为true或false来实现的。默认设置是<code>true</code>因为大多数过滤器本身需要执行,如果它们在链中配置。</p> <p>例如,在shiro.ini中:</p> <pre> <code>[main] ... # configure Shiro's default 'ssl' filter to be disabled while testing: ssl.enabled = false [urls] ... /some/path = ssl, authc /another/path = ssl, roles[admin] ... </code></pre> <p>此示例显示可能许多URL路径都可能要求请求必须由SSL连接保护。在开发过程中设置SSL可能会令人沮丧和耗时。在开发过程中,可以禁用ssl过滤器。部署到生产时,您可以使用一个配置属性启用它 - 这比手动更改所有URL路径或维护两个Shiro配置要容易得多。</p> <h3>请求特定的启用/禁用</h3> <p><code>OncePerRequestFilter</code>实际上根据其<code>isEnabled(request, response)</code>方法确定是否启用或禁用过滤器。</p> <p>此方法默认返回属性的值,<code>enabled</code>用于一般启用/禁用所有请求,如上所述。如果要根据<em>请求特定</em>条件启用或禁用过滤器,则可以覆盖该<code>OncePerRequestFilter</code><code>isEnabled(request,response)</code>方法以执行更具体的检查。</p> <h3>路径特定的启用/禁用</h3> <p>Shiro的PathMatchingFilter(一个子类)<code>OncePerRequestFilter</code>能够基于被过滤的<em>特定路径</em>对配置做出反应,这意味着除了传入的请求和响应之外,您还可以基于路径和特定于路径的配置启用或禁用过滤器。</p> <p>如果您需要能够对匹配路径和路径特定配置做出反应,以确定是启用还是禁用过滤器,而不是<code>OncePerRequestFilter</code> <code>isEnabled(request,response)</code>覆盖方法,那么您将覆盖该<code>PathMatchingFilter</code> <code>isEnabled(request,response,path,pathConfig)</code>方法。</p> <h2>会话管理</h2> <h3>Servlet容器会话</h3> <p>在Web环境中,Shiro的默认会话管理器<code>SessionManager</code>实现是<code>ServletContainerSessionManager</code>。这个非常简单的实现将所有会话管理职责(包括如果servlet容器支持它的会话群集)委托给运行时Servlet容器。它本质上是一个桥梁,用于Shiro的会话API到servlet容器,没有别的。</p> <p>使用此默认值的一个好处是,使用现有servlet容器会话配置(超时,任何容器特定的集群机制等)的应用程序将按预期工作。</p> <p>这个默认的缺点是,你绑定到servlet容器的特定会话行为。例如,如果您想集群会话,但在生产中使用Jetty进行测试和Tomcat,则容器特定的配置(或代码)将不可移植。</p> <h4>Servlet容器会话超时</h4> <p>如果使用默认的servlet容器支持,您可以在Web应用程序的<code>web.xml</code>文件中按预期配置会话超时。例如:</p> <pre> <code class="language-xml"><session-config> <!-- web.xml expects the session timeout in minutes: --> <session-timeout>30</session-timeout> </session-config> </code></pre> <h3>本地会话</h3> <p>如果希望您的会话配置设置和集群在servlet容器(例如Jetty在测试中,但是Tomcat或JBoss在生产中)是可移植的,或者您想要控制特定的会话/集群功能,您可以启用Shiro的本地会话管理。</p> <p>“Native”这个词意味着Shiro自己的企业会话管理实现将用于支持所有<code>Subject</code>和<code>HttpServletRequest</code>会话,并完全绕过servlet容器。但是放心 - Shiro直接实现了Servlet规范的相关部分,所以任何现有的web / http相关代码如预期一样工作,并且不需要“知道”Shiro是透明地管理会话。</p> <h4>DefaultWebSessionManager</h4> <p>要为Web应用程序启用本机会话管理,您需要配置一个本地的Web会话管理器来覆盖默认的基于servlet容器的会话管理器。你可以通过配置<code>DefaultWebSessionManager</code>Shiro的实例来实现<code>SecurityManager</code>。例如,在<code>shiro.ini</code>:</p> <p><strong>shiro.ini本地Web会话管理</strong></p> <pre> <code>[main] ... sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager # configure properties (like session timeout) here if desired # Use the configured native session manager: securityManager.sessionManager = $sessionManager </code></pre> <p>一旦声明,您可以配置<code>DefaultWebSessionManager</code>实例与本地会话选项,如会话超时和聚类配置,如会话管理部分所述。</p> <h5>本地会话超时</h5> <p>配置<code>DefaultWebSessionManager</code>实例后,按会话管理:会话超时中所述配置会话超时</p> <h5>会话Cookie</h5> <p>在<code>DefaultWebSessionManager</code>支持两个特定网络的配置属性:</p> <ul> <li><code>sessionIdCookieEnabled</code> (布尔)</li> <li><code>sessionIdCookie</code>,一个Cookie实例。</li> </ul>  <strong>Cookie作为模板</strong> <hr /> <p>该<code>sessionIdCookie</code>属性本质上是一个模板 - 您配置<code>Cookie</code>实例属性,并且此模板将用于在运行时使用适当的会话ID值设置实际的HTTP Cookie。</p>   <h6>会话Cookie配置</h6> <p>DefaultWebSessionManager的<code>sessionIdCookie</code>默认实例是a <code>SimpleCookie</code>。这个简单的实现允许对要在http Cookie上配置的所有相关属性进行JavaBeans风格的属性配置。</p> <p>例如,您可以设置Cookie域:</p> <pre> <code>[main] ... securityManager.sessionManager.sessionIdCookie.domain = foo.com </code></pre> <p>有关其他属性,请参阅SimpleCookie JavaDoc。</p> <p>cookie的默认名称<code>JSESSIONID</code>与servlet规范一致。此外,Shiro的cookie支持<code>HttpOnly</code>标志。该<code>sessionIdCookie</code>套<code>HttpOnly</code>到<code>true</code>默认情况下,额外的安全性。</p>  <strong>注意</strong> <hr /> <p>Shiro的<code>Cookie</code>概念<code>HttpOnly</code>甚至在Servlet 2.4和2.5环境中支持该标志(而Servlet API只在2.6或更高版本中支持它)。</p>   <h6>禁用会话Cookie</h6> <p>如果您不想使用会话Cookie,可以通过将<code>sessionIdCookieEnabled</code>属性配置为false 来禁用它们。例如:</p> <p><strong>禁用本机会话Cookie</strong></p> <pre> <code>[main] ... securityManager.sessionManager.sessionIdCookieEnabled = false </code></pre> <h2>记住我的服务</h2> <p>Shiro将执行'rememberMe'服务,如果<code>AuthenticationToken</code>实现的<code>org.apache.shiro.authc.RememberMeAuthenticationToken</code>接口。此接口指定一个方法:</p> <pre> <code>boolean isRememberMe(); </code></pre> <p>如果此方法返回<code>true</code>,则Shiro将记住会话中的最终用户身份。</p>  <strong>UsernamePasswordToken和RememberMe</strong> <hr /> <p>常用的<code>UsernamePasswordToken</code>已经实现了<code>RememberMeAuthenticationToken</code>接口并支持rememberMe登录。</p>   <h3>计划支持</h3> <p>要以程序方式使用rememberMe,可以将值设置为<code>true</code>支持此配置的类。例如,使用标准<code>UsernamePasswordToken</code>:</p> <pre> <code>UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); SecurityUtils.getSubject().login(token); ... </code></pre> <h3>基于表单的登录</h3> <p>对于Web应用程序,<code>authc</code>过滤器默认为a <code>FormAuthenticationFilter</code>。这支持将“rememberMe”布尔作为form / request参数读取。默认情况下,它期望请求参数被命名<code>rememberMe</code>。这里是一个示例shiro.ini配置支持这:</p> <pre> <code>[main] authc.loginUrl = /login.jsp [urls] # your login form page here: login.jsp = authc </code></pre> <p>在您的网络表单中,有一个名为“rememberMe”的复选框:</p> <pre> <code><form ...> Username: <input type="text" name="username"/> <br/> Password: <input type="password" name="password"/> ... <input type="checkbox" name="rememberMe" value="true"/>Remember Me? ... </form> </code></pre> <p>默认情况下,<code>FormAuthenticationFilter</code>会寻找名为请求参数<code>username</code>,<code>password</code>和<code>rememberMe</code>。如果这些不同于您在表单中使用的表单字段名称,则需要在上配置名称<code>FormAuthenticationFilter</code>。例如,在<code>shiro.ini</code>:</p> <pre> <code>[main] ... authc.loginUrl = /whatever.jsp authc.usernameParam = somethingOtherThanUsername authc.passwordParam = somethingOtherThanPassword authc.rememberMeParam = somethingOtherThanRememberMe ... </code></pre> <h3>Cookie配置</h3> <p>您可以<code>rememberMe</code>通过设置默认的{{RememberMeManager}}的各种cookie属性来配置cookie的功能。例如,在shiro.ini中:</p> <pre> <code>[main] ... securityManager.rememberMeManager.cookie.name = foo securityManager.rememberMeManager.cookie.maxAge = blah ... </code></pre> <p>请参阅<code>CookieRememberMeManager</code>和支持<code>SimpleCookie</code>JavaDoc的配置属性。</p> <h3>自定义 <code>RememberMeManager</code></h3> <p>应该注意的是,如果默认的基于cookie的实现<code>RememberMeManager</code>不能满足你的需要,你可以插入任何你喜欢的<code>securityManager</code>类似,你将配置任何其他对象引用:</p> <pre> <code>[main] ... rememberMeManager = com.my.impl.RememberMeManager securityManager.rememberMeManager = $rememberMeManager </code></pre> <h2>JSP / GSP标签库</h2> <p>Apache Shiro提供了一个<code>Subject</code>-aware JSP / GSP标签库,允许您根据当前主题的状态控制您的JSP,JSTL或GSP页面输出。这对于基于查看网页的当前用户的身份和授权状态来个性化视图是非常有用的。</p> <h3>标签库配置</h3> <p>标签库描述符(TLD)文件捆绑在<code>shiro-web.jar</code>中<code>META-INF/shiro.tld</code>文件。要使用任何标记,请将以下行添加到JSP页面的顶部(或在您定义页面指令的任何位置):</p> <pre> <code><%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> </code></pre> <p>我们使用<code>shiro</code>前缀来指示shiro标签库命名空间,但是您可以分配任何您喜欢的名称。</p> <p>现在,我们将介绍每个标记,并说明如何使用它来呈现网页。</p> <h3>该<code>guest</code>标签</h3> <p><code>guest</code>只有当前<code>Subject</code>被视为“访客”时,标记才会显示其包装内容。客人是<code>Subject</code>没有身份的任何人。也就是说,我们不知道用户是谁,因为他们没有登录,他们不记得(从记住我服务)从以前的网站访问。</p> <p>例:</p> <pre> <code class="language-xml"><shiro:guest> Hi there! Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today! </shiro:guest> </code></pre> <p>该<code>guest</code>标签是的逻辑相反的<code>user</code>标记。</p> <h3>该<code>user</code>标签</h3> <p><code>user</code>仅当当前<code>Subject</code>被视为“用户”时,标记才会显示其包装内容。在此上下文中的“用户”被定义为<code>Subject</code>具有已知标识,或者来自成功认证或者来自“记住我”服务。请注意,此标记在语义上与已认证的标记不同,后者比此标记更受限制。</p> <p>例:</p> <pre> <code class="language-xml"><shiro:user> Welcome back John! Not John? Click <a href="login.jsp">here<a> to login. </shiro:user> </code></pre> <p>该<code>user</code>标签是的逻辑相反的<code>guest</code>标记。</p> <h3>该<code>authenticated</code>标签</h3> <p>仅当当前用户<em>在其当前会话期间</em>已成功通过身份验证<em>时,</em>才显示主体内容。它比“用户”标签限制性更强。它在逻辑上与“notAuthenticated”标签相反。</p> <p>该<code>authenticated</code>标签将显示其包裹内容仅在当前<code>Subject</code>已成功验证<em>了当前会话中</em>。这是一个比用户更严格的标签,用于保证敏感工作流中的身份。</p> <p>例:</p> <pre> <code class="language-xml"><shiro:authenticated> <a href="updateAccount.jsp">Update your contact information</a>. </shiro:authenticated> </code></pre> <p>该<code>authenticated</code>标签是的逻辑相反的<code>notAuthenticated</code>标记。</p> <h3>该<code>notAuthenticated</code>标签</h3> <p>该<code>notAuthenticated</code>如果当前标签将显示其包裹内容<code>Subject</code>已<strong>不</strong>还成功地在本届会议期间进行身份验证。</p> <p>例:</p> <pre> <code class="language-xml"><shiro:notAuthenticated> Please <a href="login.jsp">login</a> in order to update your credit card information. </shiro:notAuthenticated> </code></pre> <p>该<code>notAuthenticated</code>标签是的逻辑相反的<code>authenticated</code>标记。</p> <h3>该<code>principal</code>标签</h3> <p>该<code>principal</code>标签将输出主题的<code>principal</code>(标识属性)或本金的属性。</p> <p>没有任何标记属性,标记将呈现<code>toString()</code>主体的值。例如(假设主体是字符串用户名):</p> <pre> <code class="language-xml">Hello, <shiro:principal/>, how are you today? </code></pre> <p>这是(大多数)等价于以下:</p> <pre> <code>Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today? </code></pre> <h4>类型主体</h4> <p>该<code>principal</code>标签假设默认情况下,该校长印的是<code>subject.getPrincipal()</code>价值。但是如果要打印一个<em>不是</em>主要主体的值,而是在主体的{ principal集合中另一个值,那么您可以通过类型获取该主体,并打印该值。</p> <p>例如,打印主题的用户ID(而不是用户名),假设ID在主体集合中:</p> <pre> <code>User ID: <principal type="java.lang.Integer"/> </code></pre> <p>这是(大多数)等价于以下:</p> <pre> <code>User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %> </code></pre> <h4>主要财产</h4> <p>但是如果主体(上面的默认主要主体或者“类型化”主体)是一个复杂对象而不是一个简单的字符串,并且你想引用该主体上的一个属性呢?您可以使用该<code>property</code>属性指示要读取的属性的名称(必须通过JavaBeans兼容的getter方法访问)。例如(假设主要主体是User对象):</p> <pre> <code>Hello, <shiro:principal property="firstName"/>, how are you today? </code></pre> <p>这是(大多数)等价于以下:</p> <pre> <code>Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today? </code></pre> <p>或者,结合type属性:</p> <pre> <code>Hello, <shiro:principal type="com.foo.User" property="firstName"/>, how are you today? </code></pre> <p>这在很大程度上等同于以下:</p> <pre> <code>Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today? </code></pre> <h3>该<code>hasRole</code>标签</h3> <p><code>hasRole</code>仅当当前<code>Subject</code>分配了指定的角色时,标记才会显示其包装内容。</p> <p>例如:</p> <pre> <code><shiro:hasRole name="administrator"> <a href="admin.jsp">Administer the system</a> </shiro:hasRole> </code></pre> <p>该<code>hasRole</code>标签是的逻辑相反lacksRole标记。</p> <h3>该<code>lacksRole</code>标签</h3> <p><code>lacksRole</code>仅当当前<code>Subject</code> <strong>未</strong>分配指定角色时,标记才会显示其包装内容。</p> <p>例如:</p> <pre> <code class="language-xml"><shiro:lacksRole name="administrator"> Sorry, you are not allowed to administer the system. </shiro:lacksRole> </code></pre> <p>该<code>lacksRole</code>标签是的逻辑相反hasRole标记。</p> <h3>该<code>hasAnyRole</code>标签</h3> <p>该<code>hasAnyRole</code>如果当前标签将显示其包裹内容<code>Subject</code>被分配<em>任何</em>指定的角色从一个逗号分隔的角色名称列表。</p> <p>例如:</p> <pre> <code class="language-xml"><shiro:hasAnyRoles name="developer, project manager, administrator"> You are either a developer, project manager, or administrator. </shiro:lacksRole> </code></pre> <p>该<code>hasAnyRole</code>标签目前还没有一个逻辑相反的标记。</p> <h3>该<code>hasPermission</code>标签</h3> <p><code>hasPermission</code>只有当前的<code>Subject</code>“has”(暗示)指定的权限,标签才会显示其包装的内容。也就是说,用户具有指定的能力。</p> <p>例如:</p> <pre> <code class="language-xml"><shiro:hasPermission name="user:create"> <a href="createUser.jsp">Create a new User</a> </shiro:hasPermission> </code></pre> <p>该<code>hasPermission</code>标签是的逻辑相反lacksPermission标记。</p> <h3>该<code>lacksPermission</code>标签</h3> <p><code>lacksPermission</code>只有当前的<code>Subject</code> <strong>DOES没有</strong>(暗示)指定的权限,标签才会显示其包装的内容。也就是说,用户<strong>没有</strong>指定的能力。</p> <p>例如:</p> <pre> <code class="language-xml"><shiro:lacksPermission name="user:delete"> Sorry, you are not allowed to delete user accounts. </shiro:hasPermission> </code></pre> <p>该<code>lacksPermission</code>标签是的逻辑相反hasPermission标记。</p> <h2>借给文档</h2> <p>虽然我们希望本文档帮助您与Apache Shiro正在进行的工作,社区正在不断改进和扩展文档。如果您希望帮助Shiro项目,请考虑更正,扩展或添加您需要的文档。你提供的每一点帮助扩大了社区,反过来又改善了Shiro。</p> <p>提交文档的最简单方法是通过点击以下<code>Edit</code>链接提交拉取请求,将其发送到用户论坛或用户邮件列表。</p>
  • Apache httpclient4.5 GET/POST/PUT/OPTION/DELETE工具类

    Apache httpclient4.5 GET/POST/PUT/OPTION/DELETE工具类Apache httpclient4.5 GET/POST/PUT/OPTION/DELETE工具类<br /> <br /> 该工具类使用比较新的<br /> Apache httpclient4.5版本<br /> <br /> 支持GET请求、POST请求、DELETE请求、PATCH请求、PUT请求、DELETE请求、OPTIONS请求<br /> <br /> 工具类代码如下: <pre> <code class="language-java"> import org.apache.http.Header; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.nio.charset.Charset; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 工具类 httpclient4.5 * * @author xq */ public class HttpclientUtils { private final static Logger logger = LoggerFactory.getLogger(HttpclientUtilss.class); /** * post请求 json参数 * * @param url * @param bodyJsonParams * @param headers * @return * @throws IOException */ public static String doPost(String url, String bodyJsonParams, Map<String, String> headers) throws IOException { HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Content-Type", "application/json"); httpPost.setEntity(new StringEntity(bodyJsonParams, Charset.forName("UTF-8"))); addHeader(httpPost, headers); return execute(httpPost); } /** * post k-v参数 * * @param url * @param params * @param headers * @return * @throws IOException */ public static String doPost(String url, Map<String, String> params, Map<String, String> headers) throws IOException { HttpPost httpPost = new HttpPost(url); if (params != null && params.keySet().isEmpty()) { httpPost.setEntity(getUrlEncodedFormEntity(params)); } addHeader(httpPost, headers); return execute(httpPost); } /** * patch json参数 * * @param url * @param bodyJsonParams * @param headers * @return * @throws IOException */ public static String doPatch(String url, String bodyJsonParams, Map<String, String> headers) throws IOException { HttpPatch httpPatch = new HttpPatch(url); httpPatch.setEntity(new StringEntity(bodyJsonParams)); addHeader(httpPatch, headers); return execute(httpPatch); } /** * patch k-v参数 * * @param url * @param params * @param headers * @return * @throws IOException */ public static String doPatch(String url, Map<String, String> params, Map<String, String> headers) throws IOException { HttpPatch httpPatch = new HttpPatch(url); if (params != null && !params.isEmpty()) { httpPatch.setEntity(getUrlEncodedFormEntity(params)); } addHeader(httpPatch, headers); return execute(httpPatch); } /** * PUT JSON参数 * * @param url * @param bodyJsonParams * @param headers * @return * @throws IOException */ public static String doPut(String url, String bodyJsonParams, Map<String, String> headers) throws IOException { HttpPut httpPut = new HttpPut(url); httpPut.addHeader("Content-Type", "application/json"); httpPut.setEntity(new StringEntity(bodyJsonParams, Charset.forName("UTF-8"))); addHeader(httpPut, headers); return execute(httpPut); } /** * put k-v参数 * * @param url * @param params * @param headers * @return * @throws IOException */ public static String doPut(String url, Map<String, String> params, Map<String, String> headers) throws IOException { HttpPut httpPut = new HttpPut(url); if (params != null && params.keySet().isEmpty()) { httpPut.setEntity(getUrlEncodedFormEntity(params)); } addHeader(httpPut, headers); return execute(httpPut); } /** * Delete json 参数 * * @param url * @param bodyJsonParams * @param headers * @return * @throws IOException */ public static String doDeletedoPut(String url, String bodyJsonParams, Map<String, String> headers) throws IOException { HttpDeleteWithEntity httpDelete = new HttpDeleteWithEntity(url); httpDelete.setEntity(new StringEntity(bodyJsonParams)); addHeader(httpDelete, headers); return execute(httpDelete); } /** * delete k-v参数 * * @param url * @param params * @param headers * @return * @throws IOException */ public static String doDelete(String url, Map<String, String> params, Map<String, String> headers) throws IOException { HttpDeleteWithEntity httpDelete = new HttpDeleteWithEntity(url); addHeader(httpDelete, headers); if (params != null && !params.isEmpty()) { httpDelete.setEntity(getUrlEncodedFormEntity(params)); } return execute(httpDelete); } /** * options json参数 * * @param url * @param bodyJsonParams * @param headers * @return * @throws IOException */ public static String doOptions(String url, String bodyJsonParams, Map<String, String> headers) throws IOException { HttpOptionsWithEntity httpOptions = new HttpOptionsWithEntity(url); addHeader(httpOptions, headers); httpOptions.setEntity(new StringEntity(bodyJsonParams)); return execute(httpOptions); } /** * options k-v参数 * * @param url * @param params * @param headers * @return * @throws IOException */ public static String doOptions(String url, Map<String, String> params, Map<String, String> headers) throws IOException { HttpOptionsWithEntity httpOptions = new HttpOptionsWithEntity(url); addHeader(httpOptions, headers); if (params != null && !params.isEmpty()) { httpOptions.setEntity(getUrlEncodedFormEntity(params)); } return execute(httpOptions); } /** * head请求 * * @param url * @param headers * @return * @throws IOException */ public static String doHeader(String url, Map<String, String> headers) throws IOException { HttpHead httpHead = new HttpHead(url); addHeader(httpHead, headers); return execute(httpHead); } /** * get请求 * * @param url * @param params * @param headers * @return * @throws IOException * @throws ClientProtocolException */ public static String doGet(String url, Map<String, String> params, Map<String, String> headers) throws IOException { // 参数 StringBuilder paramsBuilder = new StringBuilder(url); if (params != null && params.keySet().isEmpty()) { if (url.indexOf("?") == -1) { paramsBuilder.append("?"); } List<NameValuePair> list = new ArrayList<>(); Set<String> keySet = headers.keySet(); Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { String key = iterator.next(); String value = headers.get(key); list.add(new BasicNameValuePair(key, value)); } String paramsStr = EntityUtils.toString(new UrlEncodedFormEntity(list)); paramsBuilder.append(paramsStr); } HttpGet httpGet = new HttpGet(paramsBuilder.toString()); // 头 addHeader(httpGet, headers); return execute(httpGet); } /** * 执行请求并返回string值 * * @param httpUriRequest * @return * @throws IOException */ private static String execute(HttpUriRequest httpUriRequest) throws IOException { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { CloseableHttpResponse response = httpClient.execute(httpUriRequest); // if (response.getStatusLine().getStatusCode() == 200) {// 请求成功状态 // try (BufferedReader bufferedReader = new BufferedReader( // new InputStreamReader(response.getEntity().getContent()))) { // StringBuilder sb = new StringBuilder(); // String tmp; // while ((tmp = bufferedReader.readLine()) != null) { // sb.append(tmp); // } // return sb.toString(); // } // } Header type = response.getEntity().getContentType(); logger.debug("Type:" + type.getValue()); String defaultCharset = "UTF-8"; String charset = getCharSet(type.getValue()); if (!StringUtils.isEmpty(charset)) { defaultCharset = charset; } return EntityUtils.toString(response.getEntity(), defaultCharset); } // return null; } /** * 添加请求头部 * * @param httpUriRequest * @param headers */ private static void addHeader(HttpUriRequest httpUriRequest, Map<String, String> headers) { if (httpUriRequest != null) { if (headers != null && !headers.keySet().isEmpty()) { Set<String> keySet = headers.keySet(); Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { String key = iterator.next(); String value = headers.get(key); httpUriRequest.addHeader(key, value); } } } } /** * 获取 UrlEncodedFormEntity 参数实体 * * @param params * @return * @throws UnsupportedEncodingException */ private static UrlEncodedFormEntity getUrlEncodedFormEntity(Map<String, String> params) throws UnsupportedEncodingException { if (params != null && params.keySet().isEmpty()) { List<NameValuePair> list = new ArrayList<>(); Set<String> keySet = params.keySet(); Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { String key = iterator.next(); String value = params.get(key); list.add(new BasicNameValuePair(key, value)); } return new UrlEncodedFormEntity(list); } return null; } /** * 根据HTTP 响应头部的content type抓取响应的字符集编码 * * @param content * @return */ private static String getCharSet(String content) { String regex = ".*charset=([^;]*).*"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(content); if (matcher.find()) return matcher.group(1); else return null; } /** * 解决httpclient 的DELETE默认不支持setEntity */ static class HttpDeleteWithEntity extends HttpEntityEnclosingRequestBase { public static final String METHOD_NAME = "DELETE"; @Override public String getMethod() { return METHOD_NAME; } public HttpDeleteWithEntity(final String uri) { super(); setURI(URI.create(uri)); } public HttpDeleteWithEntity(final URI uri) { super(); setURI(uri); } public HttpDeleteWithEntity() { super(); } } /** * 解决httpclient 的OPTIONS默认不支持setEntity */ static class HttpOptionsWithEntity extends HttpEntityEnclosingRequestBase { public static final String METHOD_NAME = "OPTIONS"; @Override public String getMethod() { return METHOD_NAME; } public HttpOptionsWithEntity() { super(); } public HttpOptionsWithEntity(final String uri) { super(); setURI(URI.create(uri)); } public HttpOptionsWithEntity(final URI uri) { super(); setURI(uri); } } public static void main(String[] args) { } } </code></pre>  
  • 解决PHP程序以root启动导致部分Apache创建的文件权限不足问题

    解决PHP程序以root启动导致部分Apache创建的文件权限不足问题解决PHP程序以root启动导致部分Apache创建的文件权限不足问题<br /> For CentOS and other Red Hat distros, add the umask setting to /etc/sysconfig/httpd and restart apache. <pre> <code class="language-html">[root ~]$ echo "umask 002" >> /etc/sysconfig/httpd [root ~]$ service httpd restart</code></pre>