搜索词>>web 耗时0.0030
  • java WEB中Cookie的操作和使用

    java WEB中Cookie的操作和使用,java,cookie,web<p><strong>java WEB中Cookie的操作和使用</strong><br /> Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是各自用户自己的数据。</p> <p>java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题。</p> <p>构造Cookie对象</p> <p><strong>Cookie(java.lang.String name, java.lang.String value)</strong></p> <p>设置cookie</p> <p><strong>void setPath(java.lang.String uri) :设置cookie的有效访问路径</strong></p> <p>设置Cookie的有效访问路径,有效访问路径指的事Cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器的时就会带着Cookie信息,否则不带Cookie信息,默认是在当前web项目的路径下</p> <p><strong>void setMaxAge(int expiry) : 设置cookie的有效时间</strong></p> <p>expiry可以是正整数,负整数,和零</p> <p>正整数:表示Cookie数据保存浏览器的缓存到硬盘中,数值表示保存的时间</p> <p>负整数:表示Cookie数据保存到浏览器的内存中,浏览器关闭Cookie就丢失了</p> <p>零:表示删除同名的Cookie数据</p> <p><strong>void setValue(java.lang.String newValue) :设置cookie的值</strong></p> <p>Cookie数据类型只能保存非中文字符串类型的。可以保存多个Cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB</p> <p>发送cookie到浏览器端保存</p> <p><strong>void response.addCookie(Cookie cookie) : 发送cookie</strong></p> <p>服务器端接收cookie</p> <p><strong>Cookie[] request.getCookies() : 接收cookie</strong></p> <p> </p> <p>建立一个生命周期为session回话级别的cookie,即随着浏览器的关闭即消失的cookie</p> <pre> <code class="language-java">HttpServletRequest request HttpServletResponse response Cookie cookie = new Cookie("yourcookiename","yourcookievalue"); response.addCookie(cookie);</code></pre>   <p>建立一个自定义生命周期的cookie,可以设置他的生命周期<br />  </p> <pre> <code class="language-java">cookie = new Cookie("cookiename","cookievalue"); // 设置Cookie的有效时间 cookie.setMaxAge(20);//该cookie只存活20秒,从最后不调该cookie开始计算 // cookie.setMaxAge(-1);//该cookie保存在浏览器内存中,关闭浏览器则销毁该cookie // cookie.setMaxAge(0);//删除根该cookie同名的cookie //设置路径,这个路径即该工程下都可以访问该cookie 如果不设置路径,那么只有设置该cookie路径及其子路径可以访问 cookie.setPath("/"); response.addCookie(cookie);</code></pre> <br /> 下面介绍如何读取cookie,读取cookie代码 <pre> <code class="language-java">Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组 for(Cookie cookie : cookies){ cookie.getName();// get the cookie name cookie.getValue(); // get the cookie value }</code></pre> 上面就是基本的读写cookie的操作。我们在实际中最好进行一下封装,比如增加一个cookie,我们关注的是cookie的name,value,生命周期,所以进行封装一个函数,当然还要传入一个response对象 <pre> <code class="language-java">/** * 设置cookie * @param response * @param name cookie名字 * @param value cookie值 * @param maxAge cookie生命周期 以秒为单位 */ public static void addCookie(HttpServletResponse response,String name,String value,int maxAge){ Cookie cookie = new Cookie(name,value); cookie.setPath("/"); if(maxAge>0) cookie.setMaxAge(maxAge); response.addCookie(cookie); }</code></pre> <br /> 读取cookie的时候,为了方便我们的操作,我们希望封装一个函数,只要我们提供cookie的name,我们便可以获取cookie的value,带着这个想法,很容易想到将cookie封装到Map里面,于是进行下面的封装 <pre> <code class="language-java">/** * 根据名字获取cookie * @param request * @param name cookie名字 * @return */ public static Cookie getCookieByName(HttpServletRequest request,String name){ Map<String,Cookie> cookieMap = ReadCookieMap(request); if(cookieMap.containsKey(name)){ Cookie cookie = (Cookie)cookieMap.get(name); return cookie; }else{ return null; } } /** * 将cookie封装到Map里面 * @param request * @return */ private static Map<String,Cookie> ReadCookieMap(HttpServletRequest request){ Map<String,Cookie> cookieMap = new HashMap<String,Cookie>(); Cookie[] cookies = request.getCookies(); if(null!=cookies){ for(Cookie cookie : cookies){ cookieMap.put(cookie.getName(), cookie); } } return cookieMap; }</code></pre> 实验,新建一个简单WEB工程,创建两个jsp文件 <pre> <code class="language-html"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>放COOKIE</title> </head> <body> <% //1.创建Cookie对象 Cookie cookie = new Cookie("tokenID","123456789"); //2.设置Cookie参数 //2.1.设置Cookie的有效路径 cookie.setPath("/");//默认就是web项目的地址 //2.2.设置Cookie的有效时间 cookie.setMaxAge(60*30);//该cookie只存活秒,从最后不调该cookie开始计算 //3.把数据发送到浏览器 response.addCookie(cookie); %> </body> </html></code></pre> 读取的页面代码 <pre> <code class="language-html"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>读COOKIE</title> </head> <body> <% Cookie[] cookies = request.getCookies(); Map<String,Cookie> cookieMap = new HashMap<String,Cookie>(); if(null!=cookies){ for(Cookie cookie : cookies){ cookieMap.put(cookie.getName(), cookie); } } %> <%=cookieMap.get("tokenID").getValue() %> </body> </html></code></pre> 浏览器中F12查看网站信息<br /> <img alt="浏览器中查看cookie" class="img-thumbnail" src="/assist/images/blog/f5036603e7224a62a3de92624b22afeb.jpg" />
  • Java web 编程规范 之 controller规范

    Java web 编程规范 之 controller规范Java web 编程规范 之 controller规范
  • 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 ab 工具进行web压力测试

    apache ab 工具进行web压力测试命令: <pre> <code class="language-html">#ab -r -n 1000 -c 100 -k http://www.your.com/</code></pre> <pre> <code class="language-html">#ab -r -t 600 -c 1000 -k http://www.your.com/</code></pre> <br /> -r 遇到错误继续执行<br /> -n 请求总数量<br /> -c 并发数量<br /> -t 持续时间(秒)<br /> <br /> <br /> https://www.cnblogs.com/dragonflyer/p/6137514.html
  • java编程中通过easypoi导入excel文件并验证导入数据

    引言    现如今越来越多的web网站或者内部管理web系统都有自己的数据分析中心引言    现如今越来越多的web网站或者内部管理web系统都有自己的数据分析中心。其数据中心的数据有些来源于人工单独操作,某些来自人工搜集大量的信息后通过excel文件批量导入进系统。本博客将讲解在java编程中,通过excel文件导入数据的方法,其实现是通过国人基于Apache晦涩难懂的POI编写的easypoi框架。一.准备jdk 1.8+(由于本博客使用的spring boot框架所以jdk版本偏高,普通项目1.6即可);eclipse(由于创建的spring boot项目,eclipse中已经安装spring的插件STS)或者你自己喜欢的java IDE工具maven 3+二.创建java web项目(spring boot框架的web项目) 本人偏好使用spring boot来创建web项目。下面通过eclipse的STS创建一个spring boot项目并选择了web模块。项目结构图​三.编码3.1添加easypoi的依赖 创建好一个基于maven的项目以后都会有个pom.xml的配置文件.打开该配置文件找到dependencies节点.添加以下easypoi的依赖配置<!-- https://mvnrepository.com/artifact/cn.afterturn/easypoi-web --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.0.3</version> </dependency> 我的spring boot添加好依赖以后完整的pom.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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.xqlee.project.demo</groupId> <artifactId>demo-springboot-easypoi-excel</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-springboot-easypoi-excel</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/cn.afterturn/easypoi-web --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.0.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 3.2编写一个简单的POJO对象 编写一个劲简单的POJO对象用来做导入测试package net.xqlee.project.demo.pojo; import java.util.Date; import javax.validation.constraints.Max; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.NotBlank; import cn.afterturn.easypoi.excel.annotation.Excel; public class User { @Excel(name = "id") @NotBlank(message = "该字段不能为空") private String id; @Excel(name = "姓名") @Pattern(regexp = "[\\u4E00-\\u9FA5]{2,5}", message = "姓名中文2-5位") private String name; @Max(value=20) @Excel(name = "年龄") private Integer age; @Excel(name = "生日", importFormat = "yyyy-MM-dd") private Date birthday; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } } 或许你已经发现,在创建的pojo的属性上我添加了一些注解。其中excel的注解是用于与excel文件做映射使用的。另外的一部分是验证使用。通过上面的依赖导入我们可以看项目的maven实际导入的包中含有hibernate的验证框架。​对easypoi的验证机制就是引入了hibernate的验证框架。所以使用也是相同的。3.3编写一个handler     easypoi 的handler是用来处理一些特殊事情的。比如导入的数据某些信息不能与现有数据库中的数据冲突,那么必然会查询数据库。这样的处理是上面hibernate验证框架也无法轻易实现的。所以他这里设计了一个handler。下面是一个简单的hander,只做了打印出导入数据的信息:package net.xqlee.project.demo.handler; import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHanlderResult; import cn.afterturn.easypoi.handler.inter.IExcelDataHandler; import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cn.afterturn.easypoi.handler.impl.ExcelDataHandlerDefaultImpl; import net.xqlee.project.demo.pojo.User; /*** * 自定义验证 */ public class UserExcelHandler implements IExcelVerifyHandler<User> { private static final Logger log = LoggerFactory.getLogger(UserExcelHandler.class); /*** * 自定义验证实现 * @param user * @return */ @Override public ExcelVerifyHanlderResult verifyHandler(User user) { ExcelVerifyHanlderResult result=new ExcelVerifyHanlderResult(true);//默认设置验证通过为true //TODO================可以根据对象字段进行各种验证================= //例如:(注意正则验证在字段注解无效,也可以通过该方式来验证) if (user.getAge()<0){ result.setSuccess(false);//错误标记,该数据会放在导入的返回集合 getFailList()中 result.setMsg("年纪错误"); return result; } return result; } } 3.4编写controllerpackage net.xqlee.project.demo.controller; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import cn.afterturn.easypoi.excel.ExcelImportUtil; import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; import cn.afterturn.easypoi.handler.inter.IExcelDataHandler; import net.xqlee.project.demo.handler.UserExcelHandler; import net.xqlee.project.demo.pojo.User; @RestController public class ExcelImportController { private static final Logger log = LoggerFactory.getLogger(ExcelImportController.class); @PostMapping("excelImport.do") public void excelImport(@RequestParam("file") MultipartFile file) { ImportParams importParams = new ImportParams(); // 数据处理 UserExcelHandler handler = new UserExcelHandler(); importParams.setVerifyHanlder(handler); // 需要验证 importParams.setNeedVerfiy(true); try { ExcelImportResult<User> result = ExcelImportUtil.importExcelMore(file.getInputStream(), User.class, importParams); List<User> successList = result.getList(); List<User> failList = result.getFailList(); log.info("是否存在验证未通过的数据:" + result.isVerfiyFail()); log.info("验证通过的数量:" + successList.size()); log.info("验证未通过的数量:" + failList.size()); for (User user : successList) { log.info("成功列表信息:ID=" + user.getId() + user.getName() + "-" + new SimpleDateFormat("yyyy-MM-dd").format(user.getBirthday())); } for (User user : failList) { log.info("失败列表信息:" + user.getName()); } } catch (IOException e) { log.error(e.getMessage(), e); } catch (Exception e) { log.error(e.getMessage(), e); } } } 这里就详细的使用了easypoi导入excel的代码;主要的是首先创建一个导入的参数,参数中可以设置handler还有是否验证等。然后通过easypoi的一个静态工具类调用导入。四.演示4.1创建一个用于测试的excel文件 我这创建的excel文件内容如下:​4.2启动项目并测试 首先启动项目,我这里是spring boot项目直接运行主类就启动了:​由于我在demo中并没有编写页面只是写了一个接口,所以这里测试用了工具postman,大家可以百度。在postmain中输入接口的地址并选择提交方式。将上传的文件以form-data的方式设置,具体如下图:​重点的已经在图中圈出来了。点击postman的SEND按钮发起请求。观察eclipse控制台的日志输出:​可以看到,导入时候handler已经执行。(需注意的是handler的字段名是excel的代码中已经注明)验证结果和我们预想的一样。因年龄大于20,中文名各自失败一个。成功一条。好啦到这里通spring boot项目通过easypoi导入excel文件数据的例子就讲解完毕了。如果有疑问欢迎加入QQ群讨论提示:首选下载:demo-springboot-easypoi-excel.zip备用下载:.代码段 小部件
  • Java web项目下载图片/文件

    Java web项目下载图片/文件 <pre> <code class="language-java">import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.xql.test.common.IOUtil; @Controller public class TestController { @RequestMapping(value = "test/fileDownload") //测试 @RequestMapping(value = "test/fileDownload") public void fileDownload(HttpServletResponse response) { // 图片流 InputStream imgInputStream = null; // 输出流 OutputStream os = null; try { // 1.从网络中读取到一张图片 // 创建URL对象[这里引用的百度logo的图片地址] String imageUrl = "https://www.baidu.com/img/bd_logo1.png"; URL url = new URL(imageUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5 * 1000); // 获取图片输入流 imgInputStream = conn.getInputStream(); // 2.将inputstream流转换为byte[]/数据 byte[] imgBytes = IOUtil.inputStream2byte(imgInputStream); // 3.获得response中的输出流 os = response.getOutputStream(); // 4.设置输出的一些参数 // 4.1设置输出文件名 String fileName = imageUrl.substring(imageUrl.lastIndexOf("/"), imageUrl.length()); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // 4.2设置下载页面文件显示大小 response.addHeader("Content-Length", "" + imgBytes.length); // 4.3设置content类型 response.setContentType("application/octet-stream;charset=UTF-8"); // 5.将图片输出 os.write(imgBytes); } catch (Exception e) { System.err.println(e.getMessage()); } finally { // 6.无论成功与否关闭相应的流 try { if (imgInputStream != null) { imgInputStream.close(); } if (os != null) { os.close(); } } catch (IOException e) { System.err.println(e.getMessage()); } } } } </code></pre> 注意事项<br /> ①<strong><em>IOUtil.inputStream2byte(InputStream is) 工具类,将inputstream 转换为byte数组</em></strong><br /> <br /> ②获取的response是来自于<strong>HttpServletResponse </strong><br /> <br />  
  • Vert.x java 入门

    Vert.x java 入门,Vert.x这个框架在常规的web业务开发中估计还不是很成熟。但是了解了他的一些原理我觉得可以有一番作为。今天主要简单讲解下eclipse Vert.x是什么有什么作用。以及基于Eclipse Vert.x的入门web程序(为啥是web不是其他?因为笔者是个Java web开发人员。)。<h2>序言</h2> <p>    Vert.x这个框架在常规的web业务开发中估计还不是很成熟。但是了解了他的一些原理我觉得可以有一番作为。今天主要简单讲解下eclipse Vert.x是什么有什么作用。以及基于Eclipse Vert.x的入门web程序(为啥是web不是其他?因为笔者是个Java web开发人员。)。</p> <p> </p> <h2>一.Eclipse Vert是什么?</h2> <p>    Eclipse Vert.x是eclipse旗下的一个开源项目。Eclipse Vert.x是基于事件驱动和非阻塞的(基于netty之上,netty是一个天然的纯异步容器),换句话说这框架适合高并发的处理。目前eclipse Vert.x已经升级到了3.x版本了。Eclipse Vert.x 还挺有个特点,支持多语言。目前官方已经支持Java、javascript、Groovy、Ruby、Ceylon、Scala以及Google最新的Kotlin。多语言的支持也证实了各个语言的社区支持活跃。</p> <p> </p> <h2>二. Eclipse Vert.x能干啥?</h2> <p>     Vert.x非常灵活 ,无论是简单的网络实用程序,复杂的现代Web应用程序,HTTP / REST微服务,大容量事件处理还是完整的后端消息总线应用程序,Vert.x都非常适合。比如游戏后端开发、银行业务开发等等。</p> <p> </p> <h2>三.Eclipse Vert.x java web入门程序</h2> <h3>3.1 Eclipse Vert.x Java web环境准备</h3> <ul> <li>JDK1.8+( lambda表达式让Eclipse Vert.x语法更优雅)</li> <li>Eclipse (或者你常用的JavaIDE工具)</li> <li>Maven 3+(管理工具,也可以选择grable)</li> </ul> <h3>3.2创建一个普通的maven项目</h3> <p>项目结构图如下:</p> <p><img alt="vert.x" class="img-thumbnail" src="/assist/images/blog/661ffa89375e4af8a1da56a0c305f733.png" /></p> <h3>3.3创建第一个Eclipse Vert.x web程序</h3> <pre> <code class="language-java">package net.xqlee.project.demo.vertx; import io.vertx.core.AbstractVerticle; import io.vertx.core.impl.VertxFactoryImpl; /**  * VertX入门服务程序  *  * @author lee  *  */ public class VertXWebServer extends AbstractVerticle {        public void start() {               vertx = new VertxFactoryImpl().vertx();               vertx.createHttpServer().requestHandler(req -> {                      req.response().putHeader("content-type", "text/plain").end("Hello from Vert.x!");               }).listen(8082);               System.out.println("Server On...");        }        public static void main(String[] args) {               new VertXWebServer().start();        } }</code></pre> <h3>3.4运行上面的Eclipse Vert web程序</h3> <p>使用Java 程序的方式运行<br /> <img alt="vert.x" class="img-thumbnail" src="/assist/images/blog/adda184c10a844b98d1928292b09a441.png" /></p> <p>浏览器访问地址:localhost:8082<br /> <img alt="vert.x" class="img-thumbnail" src="/assist/images/blog/14e70211f0f6450db67b2a5b7af38baa.png" /></p> <p>可以看到上图中浏览器返回的数据。好啦第一个入门程序已经完成。</p> <p>后续将会讲解深入的Eclipse Vert.x项目实战。</p>
  • Linux后台下载工具(器)transmission 使用详解

    Linux后台下载工具(器)transmission 类似迅雷使用详解,transmission 是一款支持绝大多数Linux系统的下载工具,采用web进行管理。可以通过web添加bt下载文件下载任务也可以直接指定下载url进行下载,一切皆在web中完成,这对Linux来说简直是一个下载神器啊。transmission简述Linux后台下载工具(器)transmission 使用详解,transmission 是一款支持绝大多数Linux系统的下载工具,采用web进行管理。可以通过web添加bt下载文件下载任务也可以直接指定下载url进行下载,一切皆在web中完成,这对Linux来说简直是一个下载神器啊。
  • WebMvcConfigurerAdapter @deprecated 弃用

    ​Spring MVC 5.0 框架中,弃用了org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapterWebMvcConfigurerAdapter​Spring MVC 5.0 框架中,弃用了org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapterWebMvcConfigurerAdapter 推荐使用以下两种方式替用方式一:继承org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport例如:@Configuration public class WebMvcConfg extends WebMvcConfigurationSupport { //你的其他配置,重写方法后配置 }方式二:直接实现接口org.springframework.web.servlet.config.annotation.WebMvcConfigurer 例如:@Configuration public class WebMvcConfg implements WebMvcConfigurer { //你的具体实现及配置 }
  • spring boot filter 配置使用

    在Java编程中,web项目通常会使用一些filter处理一些特定的业务。这里主要讲解springboot中filter的几种配置和使用。<h2>引言</h2>     在Java编程中,web项目通常会使用一些filter处理一些特定的业务。这里主要讲解springboot中filter的几种配置和使用。 <h2>一.创建一个spring boot 项目</h2> 创建spring boot项目的方法这里就不详细介绍了,不清楚的可以参考:<a rel="" href="http://www.leftso.com/blog/64.html" rel="" target="_blank">spring boot 入门项目创建</a><br /> 下面是一个创建好的项目结构图:<br /> <img alt="项目结构图" class="img-thumbnail" src="/assist/images/blog/33b5edbb638b4554b07ee0e9de2c5bbe.png" /><br /> 其中主要的在于上面的config目录下的FilterConfig.java和下面的filter中两个filter的实现类。 <h2>二.Filter的实现类</h2> 这里的filter指的是javax.servlet.Filter;接口。在spring boot框架中有很多方式来实现Filter接口。下面就讲常用的两种。 <h3>2.1javax.servlet.Filter;原生接口的实现</h3> <strong>MyFilter.java:</strong> <pre> <code class="language-java">package net.xqlee.project.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 测试用filter * * @author xqlee * */ public class MyFilter implements Filter { private static final Logger log = LoggerFactory.getLogger(MyFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("MyFilter 初始化中..."); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { log.info("进入 MyFilter"); chain.doFilter(request, response); } @Override public void destroy() { log.info("MyFilter 销毁中..."); } } </code></pre> 上面的代码就是一个简单的Filter接口实现类.其中需要处理的业务一般放在doFilter方法中。 <h3>2.2继承spring的OncePerRequestFilter来实现Filter</h3> <pre> <code class="language-java">package net.xqlee.project.filter; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.filter.OncePerRequestFilter; /** * 通过继承spring提供的filter来实现filter * * @author xqlee * */ public class MyOncePerRequestFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(MyOncePerRequestFilter.class); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { log.info("进入 MyOncePerRequestFilter"); filterChain.doFilter(request, response); } } </code></pre> 说明:Spring 的OncePerRequestFilter类实际上是一个实现了Filter接口的抽象类。spring对Filter进行了一些封装处理。 <h2>三.配置Filter到容器中</h2>     上面只是创建好了两个Filter实现类。在web编程中我们知道需要在web.xml中配置相应的过滤器内容,如过滤的url,过滤器名字,参数等。spring boot框架中为配置Filter进行了一些封装使得我们可以用spring风格的方式配置Filter。<br /> 首先创建一个类,添加配置注解,并将上面的两个过滤器配置到这个配置类中: <pre> <code class="language-java">package net.xqlee.project.config; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import net.xqlee.project.filter.MyFilter; import net.xqlee.project.filter.MyOncePerRequestFilter; /** * 配置拦截器 * * @author xqlee * */ @Configuration public class FilterConfig { /** * 拦截器注册 * * @return */ @Bean public FilterRegistrationBean myFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); registration.addUrlPatterns("/a/*");// 拦截路径 registration.setName("MyFilter");// 拦截器名称 registration.setOrder(1);// 顺序 return registration; } /** * 拦截器注册 * * @return */ @Bean public FilterRegistrationBean myOncePerRequestFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyOncePerRequestFilter()); registration.addUrlPatterns("/*");// 拦截路径 registration.setName("MyOncePerRequestFilter");// 拦截器名称 registration.setOrder(2);// 顺序 return registration; } } </code></pre> <h2>四.Spring boot Filter测试</h2> 启动spring boot项目,观察启动日志:<br /> <img alt="" class="img-thumbnail" src="/assist/images/blog/d5157c396bc8402e87c5567c843a6701.png" />注意观察上图中红色圈出来的地方,我们可以看到两个filter都进行了初始化并且也显示出来了过滤器的过滤地址。<br /> <br /> 为了进一步的测试其是否作用,创建一个简单的controller进行测试 <pre> <code class="language-java">package net.xqlee.project.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/a/filter.do") public Object hello() { return "Hello Filter"; } @GetMapping("/") public Object index() { return "Welcome Index"; } } </code></pre> <br /> 浏览器访问地址http://localhost:8080/<br /> <img alt="index" class="img-thumbnail" src="/assist/images/blog/73d5d31bbfa040d6a97be4945d93a49b.png" /><br /> 观察eclipse控制台日志:<br /> <img alt="访问日志" class="img-thumbnail" src="/assist/images/blog/bae81d12286e4a5a8caa859cb14ac40a.png" /><br /> 我们可以看到只有MyOncePerRequestFilter的日志,因为从启动日志图中可以看到MyOncePerRequestFilter的过滤路径是所有,而myfilter过滤路径是/a/,所以这里只能看到MyOncePerRequestFilter的日志。<br /> <br /> 接下来访问地址:http://localhost:8080/a/filter.do<br /> <img alt="访问" class="img-thumbnail" src="/assist/images/blog/0dfedd8e8c8b43e9bc54a99247c1c102.png" /><br /> 后端日志:<br /> <img alt="" class="img-thumbnail" src="/assist/images/blog/3dd625c90b0d454eba69436e04ae5c52.png" />这次可以看到两个过滤器的日志了。同时也说明配置的过滤器已经生效。<br /> <br />