??xml version="1.0" encoding="utf-8" standalone="yes"?>
<Stoke>
<Name ID="1" Type="VarChar" Length="10" Index="True">Ada</Name>
<Sex ID="2" Type="VarChar" Length="2">female</Sex>
<Age ID="3" Type="Integer">21</Age>
<Comm>
<Mobile ID="4" Type="VarChar" Length="15">13300008888</Mobile>
<Email ID="5" Type="VarChar" Length="30">Ada@gmail.com</Email>
</Comm>
</Stoke>
上面的xml描述在数据库中创Z张表
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class XmlToSql
{
public static void getNode(NodeList nl,StringBuffer sql)
{
for(int i=0;i<nl.getLength();i++)
{
Node node = nl.item(i);
if(node.getNodeType() == Node.ELEMENT_NODE)
{
if(node.hasAttributes())
{
sql.append(node.getNodeName()+" ");
NamedNodeMap attr = node.getAttributes();
sql.append(attr.getNamedItem("Type").getNodeValue());
if(attr.getNamedItem("Length")!=null)
{
sql.append("("+attr.getNamedItem("Length").getNodeValue()+")");
}
sql.append(",");
if(attr.getNamedItem("Index")!=null && attr.getNamedItem("Index").getNodeValue().equals("True"))
{
sql.append("index index_"+node.getNodeName()+"("+node.getNodeName()+"),");
}
}
else
{
getNode(node.getChildNodes(),sql);
}
}
}
}
public static void main(String[] args)
{
try
{
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fac.newDocumentBuilder();
Document document = builder.parse(new File("Data.xml"));
Node node = document.getFirstChild();
StringBuffer sql = new StringBuffer("create table temp(id int(11) NOT NULL auto_increment,");
getNode(node.getChildNodes(),sql);
sql.append("PRIMARY KEY (id))");
Class.forName("com.mysql.jdbc.Driver");
String url ="jdbc:mysql://localhost/test";
Connection conn= DriverManager.getConnection(url,"root","root");
Statement stmt = conn.createStatement();
stmt.execute(sql.toString());
}
catch(Exception e){
e.printStackTrace();
}
}
}
//get & set
}
public class Department //专业
{
private Integer id;
private Institute institute;//学院属?/font>
private String department;
//get & set
}
下面是配置文g了:
<hibernate-mapping>
<class name="subject.model.Institute">
<id name="id">
<generator class="increment"/>
</id>
<property name="institute"/>
</class>
<class name="subject.model.Department">
<id name="id">
<generator class="increment" />
</id>
<property name="department" />
<many-to-one name="institute" class="subject.model.Institute"
column="instituteId" lazy="false"/>//多对一Qlazy="false"来将依赖延迟讄为false
</class>
</hibernate-mapping>
所谓依赖gq就是说Q如果我们把他设|ؓtrueQ那么我们得到的department中的该属性初始化为空Q否则就有该属性了Q?br />
2.l承
在我的系l中Q存在三U用P理员、学生、教师,他们都有l合的属性,也有个性的地方Q具体的cMl如下:
public abstract class User //父类用户
{
private Integer id;
private String user;
private String password;
private String name;
private String telphone;
//get & set
}
public class Student extends User//学生
{
private SchoolClass schoolClass;
private String sn;
}
public class Teacher extends User//教师
{
private String level;
private Boolean confirm;
}
public class Admin extends User//理?/font>
{
private String grade;
}
在数据库中我把三U角色的对象存放在一个表中,用一个字D|区分三种角色Q在hibernate映射l承时属于一U情况,可以参照书中的介l:
<hibernate-mapping>
<class name="subject.model.User" discriminator-value="not null"> //q里的not null很关键,没这个就会出现问?/font>
<id name="id">
<generator class="increment" />
</id>
<discriminator column="type" type="character" />
<property name="user" />
<property name="password" />
<property name="name" />
<property name="telphone" />
<subclass name="subject.model.Admin" discriminator-value="a">//存储对象cd的标识符
<property name="grade" column="sn" />//对于每种对象的字D都攑ֈ数据库的一列里?/font>
</subclass>
<subclass name="subject.model.Teacher" discriminator-value="t">
<property name="level" column="sn" />
<property name="confirm" column="about" />
</subclass>
<subclass name="subject.model.Student" discriminator-value="s">
<property name="sn" />
<many-to-one name="schoolClass" class="subject.model.SchoolClass"
column="about" lazy="false"/>
</subclass>
</class>
</hibernate-mapping>
package subject.bean;
import java.util.ArrayList;
import java.util.List;
public class Page
{
private int current = 1; //当前늠
private int nextPage = 0; //下一늠
private int previousPage = 0;//上一늠
private int total = 0;//ȝ数据
private int pages = 0;//总页?/font>
private int each = 5;//每页数据
private int start = 0;//当前늚起始数据
private int end = 0;//当前늚l束数据
private boolean next = false;//是否存在下一?/font>
private boolean previous = false;//是否存在上一?/font>
private List list = null;
//需要显C的数据
public Page( List list, int each )//以需要显C的数据和每要昄的数据ؓ参数q行初始?/font>
{
this.list = list;
this.each = each;
total = list.size();//ȝ数据{于List的大?/font>
if ( total % each == 0 )//总页数和没页昄的数据可以整除,则ؓ总页?/font>
pages = total / each;
else
pages = total / each + 1;//否则需要加上一了
if ( current >= pages )
{
next = false;//判断是否有下一?/font>
}
else
{
next = true;
nextPage = current + 1;//有,q得出来下一|多少呢!
}
if ( total < each )
{
start = 0;//q页昄多少数据啊?如果是最后一,只显C整除后的余C
end = total;
}
else
{
start = 0;//否则要显C每需要显C的数据?/font>
end = each;
}
}
public int getCurrent()
{
return current;
}
public boolean isNext()
{
return next;
}
public boolean isPrevious()
{
return previous;
}
public int getPages()
{
return pages;
}
public int getTotal()
{
return total;
}
public int getNextPage()
{
return nextPage;
}
public int getPreviousPage()
{
return previousPage;
}
@SuppressWarnings ( "unchecked" )
public List get( int page )//获取指定늠的List
{
if ( page > 0 && page <= pages )
{
current = page;//page在有效范围内则ؓ当前?/font>
}
if ( ( current - 1 ) > 0 )//计算上一|否存在以及?/font>
{
previous = true;
previousPage = current - 1;
}
else
{
previous = false;
}
if ( current >= pages )//计算下一|否存在以及?/font>
{
next = false;
}
else
{
next = true;
nextPage = current + 1;
}
if ( page * each < total )//计算昄的记录在List中的位置
{
end = current * each;
start = end - each;
}
else
{
end = total;
start = each * ( pages - 1 );
}
List gets = new ArrayList();//把显C的数据攑ֈ一个新的List?/font>
for ( int i = start; i < end; i++ )
{
gets.add( list.get( i ) );
}
return gets;
}
}
上面的Page Bean比那个就略的很多Q我们再来看看Action怎么来做Q?br />
public class AdminAction extends BaseAction
{
private AdminManager mgr;
public void setAdminManager( AdminManager mgr )
{
this.mgr = mgr;
}
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response )
throws Exception
{
Integer pageId = getInt( request, "page" );
Page page = null;
List rs =mgr.getStudents();
if ( rs != null && rs.size() != 0 )
{
page = new Page( rs, 10 );
request.setAttribute( "students", page.get( pageId ) );
}
request.setAttribute( "search", Select.studentSearch() );
}
request.setAttribute( "page", page );
return mapping.findForward("student");
}
}
q样我们可以把分页对象和List攑ֈExecute中了Q在q里我们把业务逻辑对象AdminManager的实例mgr声明成了bean的Ş式,q样可以在Spring中利用ioc来注入:
Struts的声明:
<action path="/admin" type="org.springframework.web.struts.DelegatingActionProxy" />
Spring中的声明Q?br />
<!-- 业务逻辑 -->
<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="remove*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="adminManager" parent="txProxyTemplate">
<property name="target">
<bean class="subject.service.impl.AdminManagerImpl">
<property name="dao" ref="dao" />
</bean>
</property>
</bean>
<bean name="/admin/admin" class="subject.web.action.AdminAction" singleton="false">
<property name="adminManager">
<ref bean="adminManager" />
</property>
</bean>
从而实CStruts和Spring的完暇接,singleton="false"从而可以解军_例的诟病Q?/font>
在model?我们采用了承关p?
父类user:
package subject.model;
public abstract class User extends BaseObject
{
private Integer id;
private String user;
private String password;
private String name;
private String telphone;
//set and get method
public abstract String getType(); //q个是用来反映用戯色的关键函数,在子cd?从而实现多?br />}
子类的实?
======================
package subject.model;
import subject.Constants;
public class Teacher extends User
{
private String level; //教师的职U?br />
//set and get method
public String getType()
{
return Constants.TEACHER;
}
}
================
package subject.model;
import subject.Constants;
public class Student extends User
{
private static final long serialVersionUID = 1L;
private SchoolClass schoolClass; //学生的班U?br /> private String sn; //学生的学?/p>
//set and get method
public String getType()
{
return Constants.STUDENT;
}
}
=================
package subject.model;
import subject.Constants;
public class Admin extends User
{
private String grade; //理员的U别
//set and get method
public String getType()
{
return Constants.ADMIN;
}
}
对于三者所共有的属性在数据库里,都存在一个字D?而依据不同的角色拥有不同的含?学生的班U则存放在了about?只要学生有班U?他就able,否则enable?而管理员和教师则默认?!
q种是属于一个承树(wi)存放在一个表的情?Hibernate的配|如?
<hibernate-mapping>
<class name="subject.model.User" discriminator-value="not null">
<id name="id">
<generator class="increment" />
</id>
<discriminator column="type" type="character" />
<property name="user" />
<property name="password" />
<property name="name" />
<property name="telphone" />
<subclass name="subject.model.Admin" discriminator-value="a">
<property name="grade" column="sn" />
</subclass>
<subclass name="subject.model.Teacher" discriminator-value="t">
<property name="level" column="sn" />
</subclass>
<subclass name="subject.model.Student" discriminator-value="s">
<property name="sn" />
<many-to-one name="schoolClass" class="subject.model.SchoolClass"
column="about" update="false" insert="false" />
</subclass>
</class>
</hibernate-mapping>
=============================================
上面的这些都是模型的基础,下面再讲怎么样配合Spring和Acegi实现pȝ的安全与登陆
在Spring中Hibernate的配|只介绍不说?
<!-- 定义DBCP数据?-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/subject?useUnicode=true&characterEncoding=gbk" />
<property name="username" value="root" />
<property name="password" value="" />
<property name="maxActive" value="100" />
<property name="maxIdle" value="30" />
<property name="maxWait" value="1000" />
<property name="defaultAutoCommit" value="true" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="60" />
</bean>
<!-- Hibernate -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>subject/model/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Dao对象 -->
<bean id="userDao" class="subject.dao.hibernate.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 业务逻辑 -->
<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="remove*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="userManager" parent="txProxyTemplate">
<property name="target">
<bean class="subject.service.impl.UserManagerImpl">
<property name="userDao" ref="userDao" />
</bean>
</property>
</bean>
<!-- Struts -->
<bean name="/user" class="subject.web.action.UserAction" singleton="false">
<property name="userManager">
<ref bean="userManager" />
</property>
</bean>
==================
上面具体的不用了?无非是调用和数据库的操?
下面p对Acegiq行声明?
我不用Ctrl+c和Ctrl+V的方式对Acegiq行介绍,没有意义,随便google׃大堆
我们想主要在q样的系l中需要的安全{略都有哪些?
1.用户的登?br />2.防止多个用户登陆一个帐?br />3.用户的注销
4.防止非法用户的访?br />
我这个程序所涉及到的只有q些,下面p行说?
在web.xml的声?
<!-- Acegi安全控制 Filter 配置 -->
<filter>
<filter-name>securityFilter</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>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Acegi通过实现了Filter接口的FilterToBeanProxy提供一U特D的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy来完成过滤功能,q样q化了web.xml的配|,q且利用Spring IOC的优ѝFilterChainProxy包含了处理认证过E的filter列表Q每个filter都有各自的功能?br />
<!-- ======================== FILTER CHAIN ======================= -->
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,
securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
大体上先介绍一?
httpSessionContextIntegrationFilter:每次request?HttpSessionContextIntegrationFilter从Session中获取Authentication对象Q在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前用,使之能跨多个请求?br />logoutFilter:用户的注销
authenticationProcessingFilter:处理登陆h
exceptionTranslationFilter:异常转换qo?br />filterInvocationInterceptor:在访问前q行权限?br />
q些q如在web.xml声明一pd的过滤器,不过当把他们都声明在spring中就可以享受Springl我们带来的方便了?br />
下面是对这些过滤器的具体声明:
只对有用的地方进行声明,别的地方几乎都是默许?br /><!-- ======================== FILTER ======================= -->
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/index.htm" /> d后所转向的位|?br /> <constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout.htm" /> 定义用户注销的地址Q?br /> </bean>
下面的这个过滤器Q我们根据自q需求有了自q实现Q?/p>
<bean id="authenticationProcessingFilter" class="subject.web.filter.UserAuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/> 下面会介l的用来起到认证理的作?br /> <property name="authenticationFailureUrl" value="/login.htm?error=wrong"/> 登陆p|的地址
<property name="defaultTargetUrl" value="/login.htm"/> 登陆成功的地址
<property name="filterProcessesUrl" value="/j_security_check"/> 登陆h的地址
<property name="userManager" ref="userManager"/> 自己d的属性,q样可以访问到我们的业务逻辑
<property name="exceptionMappings"> 出现异常所对应的地址
<value>
org.acegisecurity.AuthenticationException=/login.htm?error=fail 登陆p| org.acegisecurity.concurrent.ConcurrentLoginException=/login.htm?error=too 已登陆了
</value>
</property>
</bean>
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.htm?error=please"/>//如果用户没登陆就惌问,先到q里登陆?br /> <property name="forceHttps" value="false"/>
</bean>
</property>
</bean>
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/> 认证服务
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value=""/> //q里定义数据库中存放的角色和我们在这里声明的角色间是否需要加个前~Q我没加
</bean>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/admin.htm*=a q里是数据库中对应的tyep a
/student*=s ׃没有前缀和数据库里一?br /> /teacher*=t
</value>
</property>
</bean>
<bean id="loggerListener"
class="org.acegisecurity.event.authentication.LoggerListener"/> 记录事g
下面p说明我们的认证服务了Q其起到的关键作用就是用来保证用L(fng)陆n份的验证Q?br />
它将验证的功能委托给多个ProviderQƈ通过遍历Providers, 以保证获取不同来源的w䆾认证Q若某个Provider能成功确认当前用L(fng)w䆾Qauthenticate()Ҏ(gu)会返回一个完整的包含用户授权信息的Authentication对象Q否则会抛出一个AuthenticationException?br />
先声明一个管理器吧,在上面的qo器中都已l用到过?br /><!-- ======================== AUTHENTICATION ======================= -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider" /> 我仅仅用?从数据库中读取用户信息验证n?br /> </list>
</property>
<property name="sessionController">
<bean id="concurrentSessionController"
class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions">
<value>1</value>每个用户同时登陆一?br /> </property>
<property name="sessionRegistry">
<bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" />
</property>
<property name="exceptionIfMaximumExceeded" value="true" />
</bean>
</property>
</bean>
来实现唯一的一个ProviderQ从数据库验证n?br /> <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService">
<bean id="jdbcDaoImpl"
class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="usersByUsernameQuery">
<value>
select user,password,about from user where user = ? 查找用户的查询语句,只需要把你数据库中的用户和密码以及enable相对应上p
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
select user,type from user where user = ? q里是把用户和权限对应上,在appfuse中用的两个表Q我都放一个表里了Q所以就用这一个就行问题的关键是要让它能找C个字D,构成一个对?br /> </value>
</property>
</bean>
</property>
<property name="userCache"> ~存都这么写Q?br /> <bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="userCache"/>
</bean>
</property>
</bean>
</property>
</bean>
==============
对于上面登陆h的处理器我借鉴了springSideQ实现的Ҏ(gu)如下Q?br />package subject.web.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.acegisecurity.userdetails.UserDetails;
import subject.Constants;
import subject.model.User;
import subject.service.UserManager;
public class UserAuthenticationProcessingFilter extends
AuthenticationProcessingFilter
{
private UserManager userManager;
public void setUserManager( UserManager userManager )
{
this.userManager = userManager;
}
protected boolean requiresAuthentication( HttpServletRequest request ,
HttpServletResponse response )
{
boolean requiresAuth = super.requiresAuthentication( request, response );
HttpSession httpSession = null;
try
{
httpSession = request.getSession( false );
}
catch ( IllegalStateException ignored )
{
}
if ( httpSession != null )
{
if ( httpSession.getAttribute( Constants.USER ) == null )
{
if ( !requiresAuth )
{
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
if ( auth != null
&& auth.getPrincipal() instanceof UserDetails )
{
UserDetails ud = (UserDetails) auth.getPrincipal();//上面声明的sql无非是要包装成q个对象
User user = userManager.getUser( ud.getUsername() );从业务逻辑里找到用P攑ֈsession?br /> httpSession.setAttribute( Constants.USER, user );
}
}
}
}
return requiresAuth;
}
}
在看看我的login.htm在登陆成功时是怎么工作的吧Q?br />public class UserAction extends BaseAction
{
private UserManager mgr;
public void setUserManager( UserManager mgr )
{
this.mgr = mgr;
}
public ActionForward login( ActionMapping mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse response )
throws Exception
{
User user = (User) getSessionObject( request, Constants.USER );
ActionMessages msg = new ActionMessages();
if ( user != null )
{
return new ActionForward( user.getType() + ".htm", true );成功去type.htm
}
else
{
String error = getParameter( request, Constants.ERROR );
if ( error != null )对于不同的错误,都加以提C?br /> {
if ( error.equalsIgnoreCase( "wrong" ) )
msg.add( "msg", new ActionMessage( "fail.login.wrong" ) );
else if ( error.equalsIgnoreCase( "too" ) )
msg.add( "msg", new ActionMessage( "fail.login.too" ) );
else if ( error.equalsIgnoreCase( "fail" ) )
msg.add( "msg", new ActionMessage( "fail.login.fail" ) );
else
msg.add( "msg", new ActionMessage( "fail.login.please" ) );
}
else
msg.add( "msg", new ActionMessage( "fail.login.please" ) );
}
saveErrors( request, msg );
return mapping.findForward( "fail" );
}
}
当然QAcegi需要介l的东西太多了,我只把我q次认ؓ有必要解释的东西写在了上面让大家来参考,作ؓ能google到的东西Q比如对于认证的方式q有很多Q我没有详l的介绍Q在学习(fn)Acegiq程中,把它自带的例子弄清楚很关键,希望大家一起学?fn)一起共勉!
import java.text.*;
import java.util.*;
public class ExpressionModel extends Observable
{
private ArrayList<String> middle;
private ArrayList<String> right;
private String input, result;
public ExpressionModel()
{
middle = new ArrayList<String>();
right = new ArrayList<String>();
}
//判断一个字W是不是操作W?br /> private boolean isOperator( String op )
{
if( op.equals("+") || op.equals("-") || op.equals("%")
||op.equals("*")|| op.equals("/") || op.equals("(")
||op.equals(")") )
return true;
else return false;
}
//得到一个操作符的优先
private int priority( String op )
{
if( op.equals("+") || op.equals("-") || op.equals("(") )
return 1;
else if( op.equals("*") || op.equals("/") || op.equals("%") )
return 2;
else
return 0;
}
//计算两个数和一个运符得到的结?br /> private String calTwoNumber( String op, String a, String b ) throws Exception
{
double x = Double.parseDouble( b );
double y = Double.parseDouble( a );
double z = 0;
if( op.equals("+") )
z = x + y;
else if( op.equals("-") )
z = x - y;
else if( op.equals("*") )
z = x * y;
else if( op.equals("/") )
z = x / y;
else if( op.equals("%") )
z = x % y;
else
z=0;
return Double.toString( z );
}
//我们输入的中则表达式{换成逆L兰式
private void turnToRight()
{
MyStack stack = new MyStack();
String op;
int pos = 0;
StringTokenizer st = new StringTokenizer(input,"+-*/%()",true);
while( st.hasMoreElements() )
middle.add( st.nextToken() );
while(true)
{
if( isOperator( middle.get(pos) ) )
{
if( stack.getTop() == -1 || (middle.get(pos)).equals("(") )
{
stack.push( middle.get(pos) );
}
else
{
if( (middle.get(pos)).equals(")") )
{
if( !(stack.top()).equals("(") )
{
op = stack.pop();
right.add(op);
}
}
else
{
if( priority(middle.get(pos)) <= priority(stack.top()) && stack.getTop() != -1 )
{
op = stack.pop();
if( !op.equals("(") )
right.add(op);
}
stack.push( middle.get(pos) );
}
}
}
else
right.add( middle.get(pos) );
pos++;
if( pos >= middle.size() )
break;
}
while( stack.getTop() != -1 )
{
op = stack.pop();
right.add(op);
}
}
private void calculate( String expression ) throws Exception
{
input = expression;
turnToRight();
MyStack stack = new MyStack();
String op1, op2, is = null;
Iterator<String> it = right.iterator();
while(it.hasNext())
{
is = it.next();
if( isOperator(is) )
{
op1 = stack.pop();
op2 = stack.pop();
stack.push( calTwoNumber(is,op1,op2) );
}
else stack.push(is);
}
NumberFormat form = NumberFormat.getInstance();
form.setMaximumFractionDigits(5);
result = input + "=" + form.format( Double.parseDouble( stack.pop() ) );
setChanged();
notifyObservers();
}
public void input(String expression) throws Exception
{
calculate(expression);
middle.clear();
right.clear();
}
public String getResult(){
return result;
}
}
===============MyStack==============
//我们用到的自q堆栈
package expression;
import java.util.*;
public class MyStack
{
private LinkedList<String> list;
private int top;
public MyStack()
{
list = new LinkedList<String>();
top = -1;
}
public void push(String value)
{
top++;
list.addFirst(value);
}
public String pop()
{
String temp = list.getFirst();
top--;
list.removeFirst();
return temp;
}
public String top()
{
return list.getFirst();
}
public int getTop()
{
return top;
}
}
===============ExpressionController========------
//控制器组Ӟ包括一个输入域和两个按U?br />
package expression;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExpressionController extends JPanel
{
private ExpressionModel expressionModel;
private JTextField calTextField;
public ExpressionController( ExpressionModel controllerModel ) {
super();
expressionModel = controllerModel;
calTextField = new JTextField( 15 );
JButton calButton = new JButton( "计算" );
JButton delButton = new JButton( "取消" );
calButton.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent event )
{
try
{
expressionModel.input( calTextField.getText() );
calTextField.setText("");
}
catch ( Exception exception )
{
JOptionPane.showMessageDialog (
ExpressionController.this,
"误入有效表辑ּQ?, "错误",
JOptionPane.ERROR_MESSAGE );
calTextField.setText("");
}
}
}
);
delButton.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent event )
{
try
{
calTextField.setText("");
}
catch ( Exception exception )
{
calTextField.setText("");
}
}
}
);
setLayout( new FlowLayout() );
add( calTextField );
add( calButton );
add( delButton );
}
public Dimension getPreferredSize()
{
return new Dimension( 320, 40 );
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
public Dimension getMaximumSize()
{
return getPreferredSize();
}
}
================ExpressionView ==================
//用来昄l果的视?br />package expression;
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class ExpressionView extends JPanel implements Observer
{
private ExpressionModel expressionModel;
private JLabel display = new JLabel();
public ExpressionView( ExpressionModel model ) {
if( model == null )
throw new NullPointerException();
expressionModel = model;
expressionModel.addObserver( this );
add( display );
setBackground( Color.white );
setBorder( new MatteBorder( 1, 1, 1, 1, Color.black ) );
}
public void update( Observable observable, Object object )
{
display.setText( expressionModel.getResult() );
}
public Dimension getPreferredSize()
{
return new Dimension( 320, 60 );
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
public Dimension getMaximumSize()
{
return getPreferredSize();
}
}
===================Expression=====================
//最后把q些l装到这里吧
package expression;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Expression extends JApplet
{
public void init()
{
ExpressionModel model = new ExpressionModel();
ExpressionView view = new ExpressionView( model );
ExpressionController controller = new ExpressionController( model );
Container contentPane = getContentPane();
contentPane.add( view, BorderLayout.CENTER );
contentPane.add( controller, BorderLayout.SOUTH );
setSize( 320, 100 );
}
}
把这几个cL包到一个jar文g后,再创Zhtm文g来访问它
<object
classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
codebase = " WIDTH = 320 HEIGHT = 100 >
<PARAM NAME = CODE VALUE = "expression.Expression" >
<PARAM NAME = ARCHIVE VALUE = "expression.jar" >
<param name = "type" value = "application/x-java-applet;version=1.5">
<param name = "scriptable" value = "false">
</object>
q样p了,不过你的机器需要安装jre 5
<filter-mapping> <!-- https://urlrewrite.dev.java.net/manual/3.0 -->
<filter-name>rewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
它所应用到的包存攑֜lib下的urlrewrite-3.0-beta.jar
它和以上的两部分Q以?web-inf/urlrewrite.xml构成了对url地址的美?br />
打开q个文gQ我们可以看C下的声明Q?br />
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
"
<urlrewrite>
<rule>
<from>^/user/(.*).html$</from>
<to type="forward">/editUser.html\?username=$1</to>
</rule>
</urlrewrite>
q样pȝ完成了url地址的editUser.html?username=****的美?br />
如将
http://localhost/aaa/bbb.jsp?id=99&name=abc
表现为:
http://localhost/aaa/bbb/99_abc.html
配置如下Q?
<rule>
<from>/aaa/bbb/([0-9]+)_([a-z]+).html</from>
<to>/../aaa/bbb.jsp?id=$1&name=$2</to>
</rule>
]]>
public class CheckTag extends TagSupport
{
private static final long serialVersionUID = 879137944441282895L;
private String check = "";//用来验证的变?/font>
private String url = "index.jsp";//出现错误要去的页?/font>
private String msg = "";//错误的提C?/font>
private String scope = "";//要严整变量的范围
private String to = "go";
//如果验证p|Q是页面后退Q还是定位到哪里Q?/font>
public String getTo()
{
return to;
}
public void setTo( String to )
{
this.to = to;
}
public String getMsg()
{
return msg;
}
public void setMsg( String msg )
{
this.msg = msg;
}
public String getScope()
{
return scope;
}
public void setScope( String scope )
{
this.scope = scope;
}
public String getCheck()
{
return check;
}
public void setCheck( String check )
{
this.check = check;
}
public String getUrl()
{
return url;
}
public void setUrl( String url )
{
this.url = url;
}
public int doStsrtTag() throws JspException
{
return SKIP_BODY;
}
public int doEndTag() throws JspException
{
boolean valid = false;//先设Z可用
if ( scope.equalsIgnoreCase( "request" ) )//如果要检查request范围
{
valid = CheckUtil.checkRequestAttribute( pageContext.getRequest(),
check );
}
else if ( scope.equalsIgnoreCase( "session" ) )
{
valid = CheckUtil.checkSession( pageContext.getSession(), check );
}
else if ( scope.equalsIgnoreCase( "parameter" ) )
{
valid = CheckUtil.checkParameter( pageContext.getRequest(), check );
}
else if ( scope.equalsIgnoreCase( "application" ) )
{
valid = CheckUtil.checkApp( pageContext.getServletContext(), check );
}
if ( valid ) return EVAL_PAGE;//如果可用ql执行此늚其余部分
else
{//否则Q哈?/font>
try
{
if ( to.equalsIgnoreCase( "go" ) ) //现在p|了,q怎么回到你该到的地方
HtmlUtil.callParentGo(
pageContext.getOut(), msg, url );//浏览器定位到URL
else
HtmlUtil.callBack( pageContext.getOut(), msg );//后退一下页面来L
return SKIP_PAGE;//跌面的其余部分,不执?/font>
}
catch ( Exception e )
{
throw new JspException( e.toString() );
}
}
}
public void release()
{
super.release();
check = "";
url = "";
msg = "";
scope = "";
}
}
下面是用到的htmlUtil部分Q?br />
public static void callParentGo( Writer out, String msg, String url )
throws IOException
{
out.write( "<script language=\"javascript\">" );
out.write( "alert(\"" + msg + "\");" );
out.write( "parent.location.href=\"" + url + "\";" );
out.write( "</script>" );
}
public static void callBack( Writer out, String msg ) throws IOException
{
out.write( "<script language=\"javascript\">" );
out.write( "alert(\"" + msg + "\");" );
out.write( "parent.history.back();" );
out.write( "</script>" );
}
写个check.tld部v吧,
<?xml version = "1.0"?>
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<tag>
<name>check</name>
<tag-class>com.boya.subject.util.CheckTag</tag-class>
<attribute>
<name>check</name>
<required>true</required>
</attribute>
<attribute>
<name>url</name>
<required>false</required>
</attribute>
<attribute>
<name>msg</name>
<required>true</required>
</attribute>
<attribute>
<name>scope</name>
<required>true</required>
</attribute>
<attribute>
<name>to</name>
<required>false</required>
</attribute>
</tag>
</taglib>
?/font>
只要在每个页面里写下q个可以判定用h否登陆了
<%@ taglib prefix="boya" uri="/WEB-INF/check.tld" %>
<boya:check check="admin" msg="理员尚未登陆,L(fng)陆!" scope ="session"/>
如果没有登陆那么Q会自动提示到首늙陆,不错Q很完美吧?
当然不是Q?zhn)可以提出?zhn)的见解。。。?/font>
import java.util.Vector;
public class Page<E>
{
private int current = 1; //当前?br /> private int total = 0; //总记录数
private int pages = 0; //总页?/font>
private int each = 5; //每页昄
private int start = 0; //每页昄的开始记录数
private int end = 0; //每页昄的结束记录数
private boolean next = false; //是否有下一?/font>
private boolean previous = false; //是否有上一?/font>
private Vector<E> v = null;
//存放查询l果的容?/font>
public Page( Vector<E> v ,int per)
{
this.v = v;
each = per;
total = v.size(); //容器的大就是ȝ记录?/font>
if ( total % each == 0 )
pages = total / each; //计算总页?/font>
else
pages = total / each + 1;
if ( current >= pages )
{
next = false;
}
else
{
next = true;
}
if ( total < each )
{
start = 0;
end = total;
}
else
{
start = 0;
end = each;
}
}
public int getCurrent()
{
return current;
}
public void setCurrent( int current )
{
this.current = current;
}
public int getEach()
{
return each;
}
public void setEach( int each )
{
this.each = each;
}
public boolean isNext()
{
return next;
}
public void setNext( boolean next )
{
this.next = next;
}
public boolean isPrevious()
{
return previous;
}
public void setPrevious( boolean previous )
{
this.previous = previous;
}
public int getEnd()
{
return end;
}
public int getPages()
{
return pages;
}
public int getStart()
{
return start;
}
public int getTotal()
{
return total;
}
//获取下一늚对象?/font>
public Vector<E> getNextPage()
{
current = current + 1;
if ( (current - 1) > 0 )
{
previous = true;
}
else
{
previous = false;
}
if ( current >= pages )
{
next = false;
}
else
{
next = true;
}
Vector<E> os = gets();
return os;
}
//获取上一?/font>
public Vector<E> getPreviouspage()
{
current = current - 1;
if ( current == 0 )
{
current = 1;
}
if ( current >= pages )
{
next = false;
}
else
{
next = true;
}
if ( (current - 1) > 0 )
{
previous = true;
}
else
{
previous = false;
}
Vector<E> os = gets();
return os;
}
//一开始获取的
public Vector<E> gets()
{
if ( current * each < total )
{
end = current * each;
start = end - each;
}
else
{
end = total;
start = each * (pages - 1);
}
Vector<E> gets = new Vector<E>();
for ( int i = start; i < end; i++ )
{
E o = v.get( i );
gets.add( o );
}
return gets;
}
}
而对于按不同搜烦Q我们需要一个FormBeanQ一般的搜烦Q都是模p搜索,搜烦个大概,而且输入的信息中文的比重也会很大Q所以,我把对中文字W的转换攑ֈ了这个BEAN里,在进行select * from * where likeq样的查询时Q如果是like ''q样可以得到所有的记录了,我便用这个来对付没有输入查询关键字的情况Q而like '%*%'可以匚w关键字,?%也在q里d上了Q?br />
package com.boya.subject.view;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class SearchForm extends ActionForm
{
private static final long serialVersionUID = 1L;
private String key;
private String from;
public String getFrom()
{
return from;
}
public void setFrom( String from )
{
this.from = from;
}
public void reset( ActionMapping mapping, HttpServletRequest req )
{
this.key = null;
}
public String getKey()
{
return key;
}
public void setKey( String key )
{
try
{
key = new String( key.getBytes( "iso-8859-1" ), "gb2312" );
}
catch ( UnsupportedEncodingException e )
{
e.printStackTrace();
}
this.key = "%" + key + "%";
}
public String getAny(){
return "%%";
}
}
前期都做好了Q我现在p开始访问这个Action了,可是q个控制器还没写呢!q里是代?/font>
public class AdminUserAction extends AdminAction
{
private Vector<Student> ss; //用来装结果的容器
private Page<Student> ps;
//分页昄的PAGE对象
protected ActionForward executeAction( ActionMapping mapping,
ActionForm form, HttpServletRequest req, HttpServletResponse res )
throws Exception
{
if ( !isSupper( req ) )
{
return notSupper( res );//如果不是理员怎么办?
}
Service service = getService();//获取业务逻辑
SearchForm sf = (SearchForm) form;//获取搜烦FORM
String op = req.getParameter( "op" );//获取用户寚w面的操作
String search = req.getParameter( "search" );//是否执行了搜?/font>
Vector<Student> temp = null; //用于存放临时反馈l用L(fng)l果容器
if ( op == null )//如果用户没有执行?下一늚操作
{
if ( search != null )//用户如果执行了搜?br /> {
if ( sf.getFrom().equalsIgnoreCase( "class" ) )//如果是按班查找
{
ss = service.getAllStudentBySchoolClassForAdmin( sf
.getKey() );//获取from的关键字
}
else if ( sf.getFrom().equalsIgnoreCase( "name" ) )//如果是按姓名查找
{
ss = service.getAllStudentByNameForAdmin( sf
.getKey() );
}
else if ( sf.getFrom().equalsIgnoreCase( "user" ) )//如果是按用户名查?/font>
{
ss = service.getAllStudentByUserForAdmin( sf
.getKey() );
}
else
{
ss = service.getAllStudentBySnForAdmin( sf.getKey() );//按学h?/font>
}
form.reset( mapping, req );//重置搜烦表单
}
else
{
ss = service.getAllStudentForAdmin( sf.getAny() ); //用户未执行查扑ְ昄全部Q?/font>
}
if ( ss != null && ss.size() != 0 )//如果查找不ؓI,有记录,那就创徏一个分对?/font>
{
ps = new Page<Student>( ss, 10 );//查询结果和每页昄记录C为参数构件对?/font>
temp = ps.gets();//q获取第一?/font>
}
}
else//如果用户执行了操?/font>
{
if ( op.equals( "next" ) )//操作是下一?/font>
{
temp = ps.getNextPage();
}
if ( op.equals( "previous" ) )//操作是上一?/font>
{
temp = ps.getPreviouspage();
}
}
req.setAttribute( "search", SelectUtil.studentSearch() );//把搜索用到的表单攑ֈrequest?/font>
req.setAttribute( "students", temp );//该页昄的学?/font>
req.setAttribute( "page", ps );//分页对象
return mapping.findForward( "student" );//h转发
}
}
用到SelectUtil中的代码如下Q?br />/**
* 获取学生查找cd的select
* @return 学生查找cd
* 2006-5-17 9:06:12
*/
public static Vector<LabelValueBean> studentSearch()
{
Vector<LabelValueBean> s = new Vector<LabelValueBean>();
s.add( new LabelValueBean( "按学h?, "sn" ) );
s.add( new LabelValueBean( "按班U查?, "class" ) );
s.add( new LabelValueBean( "按姓名查?, "name" ) );
s.add( new LabelValueBean( "按用h?, "user" ) );
return s;
}
在看面视图前先让我们看看Model吧,
public class Student extends User
{
private String sn;
private SchoolClass schoolClass;
//q里的班U做Z一U对象,我们在视图显C的时候就有了一层嵌?/font>
public SchoolClass getSchoolClass()
{
return schoolClass;
}
public void setSchoolClass( SchoolClass schoolClass )
{
this.schoolClass = schoolClass;
}
public String getSn()
{
return sn;
}
public void setSn( String sn )
{
this.sn = sn;
}
public String getType()
{
return "student";
}
}
在了解了model后,q是看看视图吧,
先放个查询表单:
<html:javascript dynamicJavascript="true" staticJavascript="true" formName="SearchForm" />
<html:form action="/adminUser.do?search=true" onsubmit="return validateSearchForm(this)">
<html:select property="from" >
<html:options collection="search" property="value" labelProperty="label" />
</html:select>
<html:text property="key" size="16" maxlength="16"/>
<html:image src="images/search.gif"/>
</html:form>
׃模型中有嵌套Q那么我们就用到Nested标签Q其实没有嵌套也可以使用q个标签Q下面的是用于显CZ息的Q用q迨器进行遍历request范围的studentsQ你不安排范_他会自动扑ֈ的,q把每次遍历的对象v名叫studentQƈ作ؓ层次的根元素Q?/font>
<logic:iterate id="student" name="students">
<nested:root name="student">
<nested:nest property="schoolClass"><nested:write property="schoolClass"/></nested:nest>//L了student的schoolClass属性对象的schoolClass嵌套
<nested:write property="name"/> //student的名?/font>
<nested:link page="/adminActions.do?method=deleteStudent" paramId="id" paramProperty="id" onclick="return window.confirm('(zhn)真的要删除吗?')">删除</nested:link>
</nested:root>
q里是显C分对象的Q?/font>
W?lt;bean:write name="page" property="current" />?br />?lt;bean:write name="page" property="pages" />?br /> //上一|否存?/font>
<logic:equal name="page" property="previous" value="true">
<html:link page="/adminUser.do?part=student&op=previous">
<font color="6795b4">上一?lt;/font>
</html:link>
</logic:equal>
<logic:notEqual name="page" property="previous" value="true">上一?amp;nbsp; </logic:notEqual>
//下一|否存?/font>
<logic:equal name="page" property="next" value="true">
<html:link page="/adminUser.do?part=student&op=next">
<font color="6795b4">下一?lt;/font>
</html:link> </logic:equal>
<logic:notEqual name="page" property="next" value="true">下一?amp;nbsp; </logic:notEqual>
共有<bean:write name="page" property="total" />条数?br />
</logic:iterate>
到这里不知道(zhn)看明白了多,在我的这个JSP里几乎没有M的业务逻辑Q这L(fng)设计比把HTML和JAVA搀杂在一起好了很多?/font>