Monday, April 30, 2012

Run JSF 2.0 on Glassfish 2.1.1

You can add JSF 2.0 and Unified EL (EL 2) magic to Glassfish V2.1.1 in 2 ways.

1) If you want to completly replace JSF 1.x with 2.x in your glassfish V2.1.1 installation


a) Remove existing jsf-impl.jar in ${com.sun.aas.installRoot}/lib
b) Add following JSF2 and unified EL jars. i.e. jsf-api-2.1.jar, jsf-impl-2.1.jar,el-api-2.1.jar, el-impl-2.1.jar in in ${com.sun.aas.installRoot}/lib.
c) Add or update classpath-prefix=”${com.sun.aas.installRoot}/lib/jsf-api.jar;${com.sun.aas.installRoot}/lib/jsf-imp.jar;${com.sun.aas.installRoot}/lib/el-api.jar;${com.sun.aas.installRoot}/lib/el-impl.jar” in ${com.sun.aas.installRoot}/domains//config/domain.xml under as an attribute.


2) If you want to keep JSF 1.x as the default implementation on your glassfish instance but want to implement JSF 2.x only on one of your applications


a) Add el-api-2.1.jar, el-impl-2.1.jar in ${com.sun.aas.installRoot}/lib.
b) Include jsf-api-2.1.jar, jsf-impl-2.1.jar in lib directory of your application war.
c) Add add sun-web.xml under /WEB-INF/ directory of your application war with following properties
mojarra2
d) Add or update classpath-prefix=”${com.sun.aas.installRoot}/lib/el-api.jar;${com.sun.aas.installRoot}/lib/el-impl.jar” in ${com.sun.aas.installRoot}/domains//config/domain.xml under as an attribute.
Hope this helps. Enjoy!!!
Note: (This does not work in Glassfish V2.0 or V2.1)


Original file:
http://ocpsoft.org/java/jsf2-java/jsf2-how-to-add-the-magic-of-el-el2-to-jsf/

Also there is another article show the way:

Saturday, April 28, 2012

Spring+Hibernate+JSF+Ajax4jsf+Acegi+jCaptcha 做登录模块

带图片验证码的用户登录是一个系统中很常见的模块,在Java EE中有很多不同的实现,而开源世界中又给我们提供了很多优秀的框架,从而减少了我们的编码量,下面给大家简单介绍一下用 Spring+Hibernate+JSF+Ajax4jsf+Acegi+jCaptcha 如何构建一个登录模块:
    我使用这些框架的版本如下:
    Spring 2.0.1
    Hibernate 3.2
    JSF 1.2
    Acegi 1.0.5
    jCaptcha 1.0-RC6
    首先建表USERTEST,和ROLETEST,作为用户表和角色表
CREATE TABLE USERTEST
(
  USERID    NUMBER                              NOT NULL,
  USERNAME  VARCHAR2(20 CHAR)                   NOT NULL,
  PASSWORD  VARCHAR2(100 CHAR)                  NOT NULL,
  STATUS    NUMBER                              DEFAULT 1                     NOT NULL,
  ROLEID    NUMBER                              NOT NULL
)

CREATE TABLE ROLETEST
(
  ROLEID    NUMBER                              NOT NULL,
  ROLENAME  VARCHAR2(50 CHAR)                   NOT NULL,
  ROLEDESC  VARCHAR2(50 CHAR)
)

    同时给ROLETEST表添加一条记录:1    ROLE_USER    普通用户
    再给USERTEST表添加一条记录:1    admin    123    1    1
    对应的hbm.xml文件就相信大家都会写,如果用eclipse开发的话,可以使用HibernateSynchronizer插件,我使用的版本是3.1.9
    接下来就要给web.xml的配置一下了:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">
 <display-name>Demo</display-name>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/classes/applicationContext.xml
  </param-value>
 </context-param>
 <context-param>
  <param-name>javax.faces.CONFIG_FILES</param-name>
  <param-value>/WEB-INF/faces-config.xml</param-value>
 </context-param>
 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>
 <listener>
  <listener-class>
   org.acegisecurity.ui.session.HttpSessionEventPublisher
  </listener-class>
 </listener>
 <listener>
  <listener-class>
   com.sun.faces.config.ConfigureListener
  </listener-class>
 </listener>
 <filter>
  <filter-name>OpenSessionInView</filter-name>
  <filter-class>
   org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  </filter-class>
  <init-param>
   <param-name>singleSession</param-name>
   <param-value>true</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>OpenSessionInView</filter-name>
  <url-pattern>*.jsf</url-pattern>
 </filter-mapping>
 <filter>
  <filter-name>Acegi Filter Chain Proxy</filter-name>
  <filter-class>
   org.acegisecurity.util.FilterToBeanProxy
  </filter-class>
  <init-param>
   <param-name>targetClass</param-name>
   <param-value>
    org.acegisecurity.util.FilterChainProxy
   </param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>Acegi Filter Chain Proxy</filter-name>
  <url-pattern>/*</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>REQUEST</dispatcher>
 </filter-mapping>
 <filter>
  <display-name>Ajax4jsf Filter</display-name>
  <filter-name>ajax4jsf</filter-name>
  <filter-class>org.ajax4jsf.Filter</filter-class>
  </filter>
 
  <filter-mapping>
  <filter-name>ajax4jsf</filter-name>
  <servlet-name>Faces Servlet</servlet-name>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>INCLUDE</dispatcher>
  </filter-mapping>


 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.jsf</url-pattern>
 </servlet-mapping>
 </web-app>

    然后Spring的applicationContext.xml,在这里面你需要配置数据库连接、hibernate的各种策略、Acegi安全设置、jCaptcha设置等等:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.1.xsd">
 <bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName">
   <value>oracle.jdbc.driver.OracleDriver</value>
  </property>
  <property name="url">
   <value>jdbc:oracle:thin:@10.10.10.10:1521:demo</value>
  </property>
  <property name="username">
   <value>demo</value>
  </property>
  <property name="password">
   <value>demo</value>
  </property>
 </bean>

 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource">
   <ref bean="dataSource" />
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">
     org.hibernate.dialect.OracleDialect
    </prop>
    <prop key="hibernate.connection.pool_size">5</prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="cache.provider_class">
     org.hibernate.cache.OSCacheProvider
    </prop>
    <prop key="cache.use_query_cache">true</prop>
    <prop key="cglib.use_reflection_optimizer">false</prop>
   </props>
  </property>
  <property name="mappingDirectoryLocations">
   <list><!-- 这里指定了hibernate的映射目录 -->
    <value>classpath:/com/fifthlab/demo/pojo</value>
   </list>
  </property>
 </bean>

 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

 <!-- Transaction template for Managers -->
 <bean id="txProxyTemplate" abstract="true"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="transactionManager" ref="transactionManager" />
  <property name="transactionAttributes">
   <props>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="add*">PROPAGATION_REQUIRED</prop>
    <prop key="delete*">PROPAGATION_REQUIRED</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="relation*">PROPAGATION_REQUIRED</prop>
    <prop key="disconnect*">PROPAGATION_REQUIRED</prop>
    <prop key="assign*">PROPAGATION_REQUIRED</prop>
    <prop key="unassign*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_SUPPORTS</prop>
   </props>
  </property>
 </bean>

<!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX acegi part begin XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
 <!-- ======================== FILTER CHAIN ======================= -->
 <!--  if you wish to use channel security, add "channelProcessingFilter," in front
  of "httpSessionContextIntegrationFilter" in the list below -->
 <bean id="filterChainProxy"
  class="org.acegisecurity.util.FilterChainProxy">
  <property name="filterInvocationDefinitionSource">
   <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**/*.jsf=httpSessionContextIntegrationFilter,captchaValidationProcessingFilter,authenticationProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
   </value>
  </property>
 </bean>

 <bean id="httpSessionContextIntegrationFilter"
  class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
  <property name="context">
   <value><!-- 此处修复了Acegi和jCaptcha不能兼容的一个bug,在后面的版本中应该修复了 -->
    com.fifthlab.demo.dao.authentication.FixedCaptchaSecurityContextImpl
   </value>
  </property>
 </bean>

 <bean id="authenticationManager"
  class="org.acegisecurity.providers.ProviderManager">
  <property name="providers">
   <list>
    <ref local="daoAuthenticationProvider" />
   </list>
  </property>
 </bean>

 <bean id="daoAuthenticationProvider"
  class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="userDetailsService">
   <ref local="hibernate3Authentication" />
  </property>
 </bean>

 <bean id="loggerListener"
  class="org.acegisecurity.event.authentication.LoggerListener" />

 <bean id="authenticationProcessingFilter"
  class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  <property name="authenticationManager">
   <ref bean="authenticationManager" />
  </property>
  <property name="authenticationFailureUrl">
   <value>/login.jsf</value>
  </property>
  <property name="defaultTargetUrl">
   <value>/login.jsf</value>
  </property>
  <property name="filterProcessesUrl">
   <value>/j_acegi_security_check</value>
  </property>
 </bean>

 <bean id="exceptionTranslationFilter"
  class="org.acegisecurity.ui.ExceptionTranslationFilter">
  <property name="authenticationEntryPoint">
   <ref local="authenticationProcessingFilterEntryPoint" />
  </property>
 </bean>

 <bean id="authenticationProcessingFilterEntryPoint"
  class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
  <property name="loginFormUrl">
   <value>/login.jsf</value>
  </property>
  <property name="forceHttps">
   <value>false</value>
  </property>
 </bean>

 <bean id="filterInvocationInterceptor"
  class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
  <property name="authenticationManager">
   <ref bean="authenticationManager" />
  </property>
  <property name="accessDecisionManager">
   <ref local="httpRequestAccessDecisionManager" />
  </property>
  <property name="observeOncePerRequest">
   <value>true</value>
  </property>
  <property name="objectDefinitionSource">
   <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /login.jsp=ROLE_ANONYMOUS
    /success.jsp=ROLE_USER
   </value>
  </property>
 </bean>

 <!-- 用来验证用户名密码是否相符,并赋予相应的角色 -->
 <bean id="hibernate3Authentication"
  class="com.fifthlab.demo.dao.authentication.Hibernate3Authentication">
  <property name="sessionFactory">
   <ref local="sessionFactory" />
  </property>
 </bean>

 <bean id="anonymousProcessingFilter"
  class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
  <property name="key">
   <value>foobar</value>
  </property>
  <property name="userAttribute">
   <value>anonymousUser,ROLE_ANONYMOUS</value>
  </property>
 </bean>

 <bean id="httpRequestAccessDecisionManager"
  class="org.acegisecurity.vote.AffirmativeBased">
  <property name="allowIfAllAbstainDecisions">
   <value>false</value>
  </property>
  <property name="decisionVoters">
   <list>
    <ref bean="roleVoter" />
   </list>
  </property>
 </bean>

 <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" />
<!-- 下面开始添加 jcaptcha  -->
<bean id="captchaValidationProcessingFilter"
  class="org.acegisecurity.captcha.CaptchaValidationProcessingFilter">
  <property name="captchaService">
   <ref bean="captchaService" />
  </property>
  <property name="captchaValidationParameter">
   <value>j_captcha_response</value>
  </property>
 </bean>

 <!-- 用来验证图片验证码是否输入正确 --><bean id="captchaService"
  class="com.fifthlab.demo.dao.authentication.JCaptchaServiceProxyImpl">
  <property name="jcaptchaService" ref="jcaptchaService" />
 </bean>
 <bean id="jcaptchaService"
  class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService" />
 <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX acegi part end XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->

</beans>
    先解释一下上面applicationContext.xml中红色的部分是jCaptcha的一个filter,必须放在第二个位置,后面的是 acegi的filter,也就是说,要先验证图片验证码是否正确,再让acegi来验证用户名和密码。蓝色的部分是需要写的几个代码,其中有一个修复 bug的地方,如果不添加那个bean,在运行的时候就会报Cast转型的错误。下面列一下蓝色部分的代码:
FixedCaptchaSecurityContextImpl:
import org.acegisecurity.captcha.CaptchaSecurityContextImpl;
public class FixedCaptchaSecurityContextImpl extends CaptchaSecurityContextImpl {
 public int hashCode() {

  if (getAuthentication() == null) {
   return (int) System.currentTimeMillis();
  } else {
   return this.getAuthentication().hashCode();
  }
 }

}
Hibernate3Authentication:
import java.util.ArrayList;
import java.util.List;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.hibernate.Criteria;
import org.hibernate.criterion.Expression;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.fifthlab.demo.pojo.Roletest;
import com.fifthlab.demo.pojo.Usertest;
public class Hibernate3Authentication extends HibernateDaoSupport implements UserDetailsService {
 public UserDetails loadUserByUsername(final String username)
 {
  Criteria criteria = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(Usertest.class);
  criteria.add(Expression.eq(Usertest.PROP_USERNAME, username));
  List users = criteria.list();
  if (users.size() == 0)
  {
   throw new UsernameNotFoundException("User not found");
  }
  Usertest user = (Usertest) users.get(0);
  // get User roles of this user
  List<Roletest> userRoles = new ArrayList<Roletest>();
  userRoles.add(user.getRoletest());
  GrantedAuthority[] dbAuths = new GrantedAuthority[userRoles.size()];
  if (userRoles.size() == 0)
  {
   throw new UsernameNotFoundException("User has no GrantedAuthority");
  }
  // grant authority to user
  String roleName = null;
  Roletest role = null;
  for (int i = 0; i < userRoles.size(); i++)
  {
   role = (Roletest) userRoles.get(i);
   if (null != role)
   {
    roleName = role.getRolename();
    dbAuths[i] = new GrantedAuthorityImpl(roleName); 
   }
  }

  user.setAuthorities(dbAuths);

  return user;
 }
}
JCaptchaServiceProxyImpl:
import org.acegisecurity.captcha.CaptchaServiceProxy;
import com.octo.captcha.service.image.ImageCaptchaService;
import com.octo.captcha.service.CaptchaServiceException;
public class JCaptchaServiceProxyImpl implements CaptchaServiceProxy {
   
    private ImageCaptchaService jcaptchaService;
 
    public boolean validateReponseForId(String id, Object response) {
 
      try {
       boolean result = jcaptchaService.validateResponseForID(id, response);
       //System.out.println("id:"+id+"\nresponse:"+response+"\nresult:"+result);
       return result;
 
      } catch (CaptchaServiceException cse) {
        //fixes known bug in JCaptcha
       cse.printStackTrace();
        return false;
      }
    }
 
    public void setJcaptchaService(ImageCaptchaService jcaptchaService) {
      this.jcaptchaService = jcaptchaService;
    }
  }
    接下来是简单的登录页面login.jsp和登录成功后的跳转页面success.jsp:
login.jsp:
<%@ page language="Java" contentType="text/html;charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax" prefix="a4j"%>
<f:view>
 <html>
 <head>
 <title>hello</title>
 </head>
 <META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
 <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
 <META HTTP-EQUIV="Expires" CONTENT="Expires">
 <body>

 <h:form id="form1">
  <h:panelGrid columns="1">
   <h:panelGroup>
    <h:outputLabel value="username:" for="username" />
    <h:inputText id="username" value="#{loginBean.userName}" />
   </h:panelGroup>
   <h:panelGroup>
    <h:outputLabel value="password:" for="password" />
    <h:inputSecret id="password" value="#{loginBean.password}" />
   </h:panelGroup>
   <h:panelGroup>
    <h:outputLabel value="verifying code:" for="verifyingCode" />
    <h:inputText id="verifyingCode" value="#{loginBean.verifyingCode}" />
    <a4j:mediaOutput element="img" cacheable="false" session="false"
        createContent="#{captchaImageBean.paint}" id="showPic"
        mimeType="image/jpeg" />
    <a4j:commandLink reRender="showPic" requestDelay="40" >
     <h:outputText value="refresh" />
    </a4j:commandLink>
   </h:panelGroup>
   <h:panelGroup>
    <h:commandButton id="commandButton1" value="Submit"
     action="#{loginBean.authenticate}" />
   </h:panelGroup>
  </h:panelGrid>
 </h:form>

 </body>
 </html>
</f:view>

    其中红色部分是应用了Ajax4jsf这个框架的两个标签,<a4j:mediaOutput> 是表示输出一个媒体,这里我选择的是输出图片,它会异步的产生图片,而不必和页面载入时同步取图片。而<a4j:commandLink reRender="showPic"> 则是在看不清图片的情况下通过异步的方式刷新上面那个<a4j:mediaOutput>的图片。
    success.jsp的页面很简单,就是显示一个“Welcome here”的字样,因此不列出来了。
    然后我们看一下页面中用到的backing bean的代码:
LoginBean:
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.fifthlab.demo.dao.authentication.JCaptchaServiceProxyImpl;
public class LoginBean extends HibernateDaoSupport {
 private static final long serialVersionUID = 1L;
 private String userName;
 private String password;
 private String verifyingCode;
 private AuthenticationManager authenticationManager;
 private JCaptchaServiceProxyImpl captchaService;
 /**
  * @return 返回用户输入的验证码
  */
 public String getVerifyingCode()
 {
  return this.verifyingCode;
 }

 /**
  * @param verifyingCode 设置图片验证码
  */
 public void setVerifyingCode(String verifyingCode)
 {
  this.verifyingCode = verifyingCode;
 }

 /**
  * @return 返回captchaService来验证图片验证码
  */
 public JCaptchaServiceProxyImpl getCaptchaService()
 {
  return this.captchaService;
 }

 /**
  * @param captchaService 设置图片验证码服务
  */
 public void setCaptchaService(JCaptchaServiceProxyImpl captchaService)
 {
  this.captchaService = captchaService;
 }

 /**
  * @return 返回密码
  */
 public String getPassword()
 {
  return password;
 }
 /**
  * @param password 设置密码
  *           
  */
 public void setPassword(String password)
 {
  this.password = password;
 }
 /**
  * @return 返回用户名
  */
 public String getUserName()
 {
  return userName;
 }
 /**
  * @param userName 设置用户名
  *           
  */
 public void setUserName(String userName)
 {
  this.userName = userName;
 }
 /**
  * @return 返回验证管理器
  */
 public AuthenticationManager getAuthenticationManager()
 {
  return authenticationManager;
 }
 /**
  * @param authenticationManager 设置验证管理器
  *           
  */
 public void setAuthenticationManager(AuthenticationManager authenticationManager)
 {
  this.authenticationManager = authenticationManager;
 }

 public String authenticate()
 {
  try
  {
   String sessionid = ((HttpSession)FacesContext.getCurrentInstance()
           .getExternalContext()
           .getSession(false)).getId();
   boolean captchaResult = getCaptchaService().validateReponseForId(sessionid, getVerifyingCode());//验证图片验证码
     UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
     getUserName(), getPassword());
   //验证用户名和密码
   Authentication auth = getAuthenticationManager().authenticate(authReq);
   String result = "failure";
   if(auth.isAuthenticated() == true && captchaResult)
   {//如果图片验证码和帐户全部验证通过
    result = "succeed";
    //把验证信息保存的上下文中
    SecurityContext secCtx = SecurityContextHolder.getContext();
    secCtx.setAuthentication(auth);
   }
   
   return result;
  }
  catch(AuthenticationException e)
  {
   e.printStackTrace();
   return "failure";
  }
 }
}
CaptchaImageBean:
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.octo.captcha.service.image.ImageCaptchaService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class CaptchaImageBean {
 static final long serialVersionUID = 1L;
 private ImageCaptchaService jcaptchaService;

 public void setJcaptchaService(ImageCaptchaService jcaptchaService) {
  this.jcaptchaService = jcaptchaService;
 }

 public void paint(OutputStream out, Object data) throws IOException
 {
  byte[] captchaChallengeAsJpeg = null;
  ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();

  HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance()
        .getExternalContext().getRequest();

  String captchaId = ((HttpSession)FacesContext.getCurrentInstance()
    .getExternalContext()
    .getSession(false)).getId();

  BufferedImage challenge = jcaptchaService.getImageChallengeForID(
    captchaId, request.getLocale());
  JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);
  jpegEncoder.encode(challenge);
  captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

  jpegOutputStream.close();
  out.write(captchaChallengeAsJpeg);
  out.flush();
  out.close();
 }
}
    最后当然是配置faces-config.xml了,里面配置了和Spring的整合、导航、managed bean等等:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>
 <application>
  <variable-resolver>
   org.springframework.web.jsf.DelegatingVariableResolver
  </variable-resolver>
 </application>
 <managed-bean>
  <managed-bean-name>loginBean</managed-bean-name>
  <managed-bean-class>com.fifthlab.demo.backingbean.LoginBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
   <property-name>authenticationManager</property-name>
   <value>#{authenticationManager}</value>
  </managed-property>
  <managed-property>
   <property-name>captchaService</property-name>
   <value>#{captchaService}</value>
  </managed-property>
 </managed-bean>

 <managed-bean>
  <managed-bean-name>captchaImageBean</managed-bean-name>
  <managed-bean-class>com.fifthlab.demo.backingbean.CaptchaImageBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
   <property-name>jcaptchaService</property-name>
   <value>#{jcaptchaService}</value>
  </managed-property>
 </managed-bean>

 <navigation-rule>
  <from-view-id>/login.jsp</from-view-id>
  <navigation-case>
   <from-outcome>succeed</from-outcome>
   <to-view-id>/success.jsp</to-view-id>
  </navigation-case>
  <navigation-case>
   <from-outcome>failure</from-outcome>
   <to-view-id>/login.jsp</to-view-id>
  </navigation-case>
 </navigation-rule>
</faces-config>




 
    大功告成!让我们来看一下演示吧



 


 










    填好帐户和验证码后,点击Submit,如果失败则还是该页不变,如果成功则跳转到:




需要的各种lib列表如下图:
 

 
















原文:http://farmerinchina.blog.sohu.com/70466803.html

Friday, April 27, 2012

Deploy own version JSF 2.0 on JBoss 6

1. Put your own jsf jar files in the WEB-INF/lib like WEB-INF/lib/jsf2.0.6
2. Add below context parameters in web.xml



<context-param>

    <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>

    <param-value>true</param-value>

</context-param>

3. Add Listener for JBoss to avoid "Could not find Factory:javax.faces.context.FacesContextFactory" excption if it is necessary.



<listener>

    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>

</listener>

Tuesday, January 31, 2012

2011年最火爆的8大Web开发工具

2011年最火爆的8大Web开发工具提到,jQuery和jQuery Mobile,CSS3 PIE,Bootstrap,LESS,Chrome开发人员工具等。一下是全部内容,

2011年最火爆的8大Web开发工具 TechFrom2011总结系列

2011年最火爆的8大Web开发工具:
Web应用开发和部署工具,Bootstrap

Twitter 于8月份推出了一个名为Bootstrap的开发工具包,将Web应用开发与部署变得更为简单快捷。Bootstrap包是一个简单的程序库,同时提供优雅的HTML和CSS规范。Bootstrap使用了一些最新的Web浏览器技术,向开发者提供时尚的排版、样式、按钮、表格、网格、导航等服务,而且占用资源很小,用gzip压缩后只有6K左右。
jQuery和jQuery Mobile,JavaScript代码工具

jQuery是一款免费且开放源代码的JavaScript代码库,而jQuery Mobile是jQuery在手机和平板上的版本。

jquery.jpg

jQuery Mobile不仅能给主流移动平台带来jQuery核心库,还能发布一个完整统一的jQuery移动UI框架,支持全球主流的手机、平板、电子阅读器、台式电脑等平台。据微软关于jQuery的调查显示,jQuery在受访网站中的使用率已从2010年12月的27%上升到2011年12月的42%。
CSS代码工具,CSS3 PIE

CSS3 PIE,全称是 Progressive Internet Explorer,可以让IE6至IE8的所有版本实现大多数的CSS3修饰特性,如圆角、阴影、渐变等等。通过这个工具CSS3 PIE,开发者可以在线修改想要的效果,并即时生成css代码。
开发管理工具,LESS,免费开源

LESS是一个CSS开发管理的强大工具,拓展了CSS的变量、运算符、include、嵌套规则等语法。

less.jpg

LESS从Ruby的LESS library衍生而来,免费开源,实现了和CSS的无缝结合。此外,LESS可以配置成自动最小化所生成的CSS文件,不仅可以节省带宽,还可以改善最终用户的体验。
Chrome开发人员工具

火狐即将死亡的预言或许被夸大其词了,但可以肯定的是Chrome正在侵蚀越来越大的市场份额,其中最主要的一个原因是Web开发人员喜欢Chrome捆绑自带的开发人员工具。

Chrome开发人员工具主要基于WebKit网络检查器(开放源代码WebKit项目的一部分),可让Web开发人员随时随地对网页的CSS、HTML和JavaScript进行实时编辑、调试以及监控。

Chrome开发人员工具不仅能帮助诊断、修复在网页加载、脚本执行以及页面呈现中出现的问题,还可帮助最大限度地了解网页或网络应用程序对CPU以及内存的使用情况。
基于浏览器的Web网络开发IDE工具,SourceKit 和 Ace

网络开发工具中文本编辑工具最受欢迎的是 Vim,但是基于web浏览器的网络IDE开发工具是 Ace,和基于 Ace 构建的SourceKit,之前的名字是 “Bespin” 和 “Skywriter” 。
PhoneGap,基于html5 的开源移动开发框架

之前在基于html5的跨平台手机应用,移动开发开源框架PhoneGap 和跨平台手机应用,移动开发开源框架PhoneGap,基于html5,已支持 facebook登陆中,介绍过移动开发 html5 开源技术框架,其母公司 Nitobi Software> 已经被Adobe公司收购。

另外,还有更多的移动和网络应用开发 10大优秀开发框架推荐,和 全功能框架平台 Strobe,基于html5的全功能应用开发平台 Strobe,由前苹果核心员工和技术大牛联合创建。


本文科技源TechFrom地址:: http://www.techfrom.com/20315.html