• 【Struts2+Spring3+Hibernate3】SSH框架整合实现CRUD_1.1


    作者: hzboy192@192.com
    Blog: http://my.csdn.net/peng_hao1988
    版本总览:http://blog.csdn.net/peng_hao1988/article/details/9026897

    实现步骤(在上一版本上修改)

    一、①.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_3_0.xsd" version="3.0">
      <display-name></display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <listener>
        <description>Spring core configuration</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
      		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
      	</filter-class>
      	 <init-param>
      		<param-name>config</param-name>
      		<!-- 示例中将struts2的配置文件struts.xml文件放到了WEB-INF根目录下 -->
      		<param-value>struts-default.xml,struts-plugin.xml,../struts.xml</param-value>
    	</init-param>
      </filter>
      <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.action</url-pattern>
        <!-- 这里很关键,如果不配置,从JSP页面就不能通过JSP标签转向到action -->
        <dispatcher>REQUEST</dispatcher> 
        <dispatcher>FORWARD</dispatcher>
      </filter-mapping>
    </web-app>

              注意上述配置,dispatcher中添加REQUEST和FORWARD两个配置,为了启用request和forward请求过滤,这样就可以使用request转发到action。
       ②.spring配置文件中使用properties文件配置数据源(示例的db-config.properties文件放在WEB-INF下)代码如下:

    <!-- 配置spring资源文件 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">  
        <list>  
    	<value>/WEB-INF/db-config.properties</value>  
        </list>  
    </property>  
    </bean> 
    
    <!-- 数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    	<property name="driverClassName" value="${driverClass}">
    	</property>
    	<property name="url" value="${url}">
    	</property>
    	<property name="username" value="${username}"></property>
    	<property name="password" value="${password}"></property>
    </bean>

        ③.db-config.properties文件的内容如下:

    ## database driver class
    driverClass=com.mysql.jdbc.Driver
    ## connection url 
    url=jdbc:mysql://localhost:3306/study
    ## user name and password for database
    username=root
    password=admin
    ## hibernate dialect
    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
    ## create or update database
    hibernate.hbm2ddl.auto=update
    ## whether show SQL
    hibernate.show_sql=false
    hibernate.format_sql=true

    欢迎页面index.jsp页面通过转发或重定向到login.jsp,代码如下: 

    <s:form action="userManagerAct" namespace="/" method="post" theme="simple">
    	<table>
    		<tr>
    			<td>username</td><td><s:textfield name="user.uname"/></td>
    			<td>password</td><td><s:password name="user.password"/></td>
    			<td colspan="2">
    				<s:submit value="submit" />
    				<s:reset value="reset"/>
    			</td>
    		</tr>
    	</table>
    </s:form>

             因为login.jsp中使用了struts标签,所以需要重action中进入页面,否则会报错!如果不想通过action到页面,可以在login.jsp中使用普通html标签,然后用EL表达式辅助回显。

    二、从欢迎页面index.jsp到login.jsp有多种方式,body中的代码如下: 

    <%--(1). 转发一个HTML文件,JSP文件,或者是一个程序段. 
    <jsp:forward page="/userManagerAct.action"></jsp:forward>
    --%>
     
    <%--(2). 通过request转发
    <% 
    request.getRequestDispatcher("/userManagerAct.action").forward(request, response);
    %>
    --%>
    <%--(3). 重定向 --%>
    <% 
    response.sendRedirect("userManagerAct.action");
    %>
    

             上述三种方式中(1)、(2)为请求转发,(3)为重定向,前两种方式能成功的前提条件是web.xml文件中将request好forward配置到了struts2的filter-mapping中了,否则会报404错误!

    三、在通过struts标签请求action是注意:
        不要在action名称后面添加后缀(本例中后缀为*.action),因为使用struts标签会自己处理后缀,如果添加了后缀,后台会抛出一个警告

    No configuration found for the specified action: 'xxxx.action' in namespace: '/'. Form action defaulting to 'action' attribute's literal value.

            网上一部分资料中说上述警告是由于没有添加namespace导致的,但是本人测试时发现不给action添加后缀,无论有无namespace都没有发现警告,若添加上后缀就会出现警告。具体什么原因就不详究了,大家在开发是注意不要给struts2标签请求的action名称后加后缀,form中最好添加上namespace。非struts2标签的请求(普通的html标签、js、以及如index.jsp中)必须添加后缀(如果在web.xml中配置了后缀的话)。

    四、拦截器(Interceptor)配置,实现用户登录状态验证,操作权限验证。如示例中登录状态验证和删除权限验证配置如下:

    <package name="myApp" extends="struts-default">
    	<interceptors>
    		<interceptor name="loginInterceptor" class="com.hzboy.common.LoginInterceptor"/>
    		<interceptor name="delInterceptor" class="com.hzboy.common.DelInterceptor"/>
    		<!-- 自定义拦截器栈,扩展原有拦截器特性 -->
    		<interceptor-stack name="MyInterceptors">
    			<interceptor-ref name="defaultStack"/>
    			<interceptor-ref name="loginInterceptor"/>
    		</interceptor-stack>			
    		<!-- 定义删除信息拦截器栈 -->
    		<interceptor-stack name="delInterceptors">
    			<interceptor-ref name="MyInterceptors"/>
    			<interceptor-ref name="delInterceptor"/>
    		</interceptor-stack>
    		
    	</interceptors>
    	<!-- 修改默认拦截器,在默认拦截器的基础之上添加了登录验证 -->
    	<default-interceptor-ref name="MyInterceptors"/>
    	
    	<global-results>
    		<result name="login">/login.jsp</result>
    		<result name="query">/WEB-INF/jsp/success.jsp</result>
    	</global-results>
    	
    	<action name="userManagerAct" class="userAct" method="doLogin">
    		<!-- 因为修改了默认拦截器,添加了登录验证,所以不能再使用默认的拦截器,登录请求不需要验证,故使用struts默认的拦截器 -->
    		<interceptor-ref name="defaultStack"/>
    	</action>
    	
    	<action name="query" class="userAct" method="doQuery" />
    	
    	<action name="delete" class="userAct" method="doDelete">
    		<interceptor-ref name="delInterceptors"/>
    		<result name="delMsg">/WEB-INF/jsp/message.jsp</result>
    	</action>
    	
    	<action name="edit" class="userAct" method="doEdit">
    		<result name="editUser">/WEB-INF/jsp/editUser.jsp</result>
    	</action>
    	
    	<action name="add" class="userAct" method="doAdd">
    		<result name="addUser">/WEB-INF/jsp/addUser.jsp</result>
    	</action>
    </package>

             ①. 自定义拦截器:在package中定义,并且可以通过package的继承来被其他的子package引用,可以将多个拦截器在interceptor-stack中引用组成一个拦截器栈,拦截器栈会按照引用的顺序依次执行。action中添加拦截器或拦截器栈使用interceptor-ref来实现。如果想让某个拦截器或拦截器栈作为默认拦截器(即替换原有的defaultStack)可以使用default-interceptor-ref来指定。默认的拦截器会拦截前包和子包中的所有action请求,所以除非当前包下所有action都需要某个拦截操作,否则没有必要指定default-interceptor-ref、如果指定一定要,那应该指定一个拦截器栈,而且该栈中引用了defaultStack。
    注意:当action应用一个拦截或拦截器栈(未引用defaultStack)时,struts2默认的拦截器就会失效,会导致部分功能无法使用,如struts2标签的回显。
            ②.定义拦截器:定义一个java类继承com.opensymphony.xwork2.interceptor.AbstractInterceptor类并实现其intercept方法,以LoginInterceptor为例,代码如下:

    public class LoginInterceptor extends AbstractInterceptor{
    
    	private static final long serialVersionUID = 1L;
    	
    	private Logger logger = Logger.getLogger(LoginInterceptor.class);
    	
    	@Override
    	public String intercept(ActionInvocation ai) throws Exception {
    		logger.info("LoginInterceptor is runing....");
    		Object user = ai.getInvocationContext().getSession().get(Global.SESSION_USER_INFO);
    		if(user != null)
    			return ai.invoke();
    		else
    			return Global.RESULT_LOGIN;
    	}
    
    }

             通过参数ActionInvocation类的invoke()方法返回到控制器继续执行后面的拦截器,如果没有就直接转发到请求的action,可以返回一个字符串到指定页面或action,该字符串应该是被拦截的action中的result的name值或是global-results中某个result的name值,否则就报404。详细的struts2拦截器配置及介绍参见网友博文:http://blog.csdn.net/qjyong/article/details/1824607 。

    五、属性验证、Validate
             ①.通常从web页面提交到action的数据需要做一些有效性验证,常见的就是在action中直接验证属性值,如下实例中的添加用户代码:

    	/**
    	 * @description 人员信息添加
    	 * @return
    	 * @author porter
    	 * @created 2013-6-2 下午6:13:56
    	 */
    	public String doAdd(){
    		logger.info("doAdd is runing...");
    		String result = Global.RESULT_QUERY;
    		try {
    			String param = (String)this.requestGetParam("param");
    			if(param != null && Integer.parseInt(param) > 0){
    				if(validatation()){
    					this.user.setId(0);
    					userService.addUser(this.user);
    					result = doQuery();
    				}else
    					result = Global.RESULT_ADD_USER;
    			}else
    				result = Global.RESULT_ADD_USER;
    		} catch (Exception e) {
    			logger.error(e);
    		}
    		return result;
    	}
    	
    	/**
    	 * @description 验证添加的人员信息
    	 * @return
    	 * @author porter
    	 * @created 2013-6-2 下午6:14:24
    	 */
    	public boolean validatation() {
    		if(this.user.getUname() == null || this.user.getUname().isEmpty()){
    			this.addFieldError("user.uname", "Username cant not be null!");
    			return false;
    		}else if(this.user.getPassword() == null || this.user.getPassword().isEmpty()){
    			this.addFieldError("user.uname", "password cant not be null!");
    			return false;
    		}
    		return true;
    	}

            添加用户信息是用户名和密码不能为空,如果不符合要就就踢回到web页面并提示用户,提示信息可以使用addActionError,addFieldError,addActionMessage。 三种消息的用法介绍(引用
         ②.还有一种验证方式:使用xml描述来验证action中的属性即validate框架。该框架需要额外添加xml配置,比较麻烦,实际开发中使用较少,详细可参见网友博文

    六、struts-json,通过ajax和json-plugin来实现数据的后台验证,如实例中添加用户信息界面,当输入完成用户名后使用ajax去有后台验证用户名是否以被占用。实例代码:

    <!-- 配置JSON响应方法 -->
    <package name="my-json" extends="json-default">
    	<action name="checkUName" class="userAct" method="checkUName">
    		<result type="json"  name="success">
    			<!-- 只返回user.name的值,没有key -->
    			<param name="root">user.uname</param>
    			
    			<!-- 需要去除的属性
    			<param name="excludeProperties">userService,users,searchText</param>
    			 -->
    			<!-- 需要包含的属性 
    			<param name="includeProperties">user\.uname</param>
    			-->
    		</result>
    	</action>
    </package>

               result中type值的取值范围和ajax数据格式基本一致,有json,xml、text等,name值可以随意,但是action执行完后返回的结果必须和这里的name值匹配。param参数有一下几种:
              1.root参数:从返回结果中根据ognl表达式取出你需要输出的结果
              2.excludeNullProperties 参数:表示是否去掉空值, 默认值是false,如果设置为true会自动将为空的值过滤,只输出不为空的值。
              3.ignoreHierarchy 参数:表示是否忽略等级,也就是继承关系,比如:TestAction继承于BaseAction,那么TestAction中返回的json字符串默认是不会包含父类BaseAction的属性值,ignoreHierarchy值默认为true,设置为false后会将父类和子类的属性一起返回
              4.includeProperties 参数:输出结果中需要包含的属性值,这里正则表达式和属性名匹配,可以用“,”分割填充多个正则表达式。
              5.excludeProperties 参数:输出结果需要剔除的属性值,也支持正则表达式匹配属性名,可以用“,”分割填充多个正则表达式。      
              页面js中的代码如下:

    $(function(){
    	//给用户名输入框设置焦点事件,当失去焦点是触发事件,判断用户输入的用户名是否合法!
    	$("input[name='user.uname']").blur(function(){
    		var uname = $(this).val();
    		if(uname == ""){
    			$("#chkMsg").css({"color":"red"});
    			$("#chkMsg").text("用户名不能为空!");
    			return;
    		}
    		$.ajax({
    			type:"post",
    			url:"checkUName.action",
    			data:{"uname":uname},
    			dataType:"json",
    			success:function(data){
    				if(data == null){
    					$("#chkMsg").css({"color":"#00cc00"});
    					$("#chkMsg").text("该用户名可以使用!");
    				}else{
    					$("#chkMsg").css({"color":"red"});
    					$("#chkMsg").text("该用户名已被使用!");
    				}
    			}
    		});
    	});
    });

            注意:使用struts-json来完成数据交换需要添加struts2-json-plugin-2.x,x.jar到工程的classpath中。

    示例代码:http://download.csdn.net/detail/peng_hao1988/5542325


    》》》》》》》》》》》》转载请注明出处《《《《《《《《《《《《



  • 相关阅读:
    AutoLayout相关
    Xcode
    ios 如何更改包名
    xcode 没有 iphone 模拟器
    使用asi请求的步骤
    caseInsensitiveCompare : 不区分大小写的 字符串比较
    封装的网路请求类
    石材网..搜索时无法正常返回数据 转码问题 (URL中用到的编码解码问题)
    谈一下我对于指针的理解
    IOS面试题--004
  • 原文地址:https://www.cnblogs.com/pocter/p/3684469.html
Copyright © 2020-2023  润新知