东东东 陈煜东的博客

标签存档: struts 2

java struts 2伪静态url rewrite重写

在开发网页的过程中,需要改写(url rewrite)一些URL地址,避免暴露一些具体的文件夹位置。

比如使用http访问/archives/2.html,实际上是访问/post?id=2这个页面,但是后者对搜索引擎不好,而且将来如果想用/article?articleID=2来替换/post?id=2,这样需要对许多页面进行更改,不方便,搜索引擎的搜录也会减少。通过此方法还可以隐藏jsp后缀名。所以使用URL rewrite技术可以实现我们的这个需求。

如果你不知道什么是url重写这个概念,可以看看相关的资料。好了,我们继续。

在struts 2项目中,使用URL rewrite需要使用的UrlRewriteFilter这个类库,下载地址http://tuckey.org/urlrewrite/

官网上的步骤写的很清楚,先添加jar包,配置过滤器,添加url rewrite规则。

要注意是

1.在web.xml中配置filter过滤器,UrlRewriteFilter 要先写,struts后写。

2.在web.xml中struts的过滤器要这样写

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

如果没有REQUESTINCLUDE,在映射到action的时候,会出现404 not found错误。如果是映射jsp文件,则不会发生错误。对于REQUEST和INCLUDE在页面使用一些东西的时候,会出现错误。比如异常The Struts dispatcher cannot be found或者 This is usually caused by using Struts tags without the associated filter。所以,当出现问题的时候,请务必加上REQUESTINCLUDE

我就因为这样的原因,郁闷了一段时间,redirect可以工作,forward却不能工作。

3.在urlrewrite.xml中,对应的规则,如果是接收的参数有多个,不用&,而是使用&amp;进行分开。

例如,应该这样写

<rule>
     <from>/products/([0-9]+)/([0-9]+).html</from>
     <to>/products/index.jsp?product_category=$1&amp;id=$2</to>
</rule>

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: java struts 2伪静态url rewrite重写 – https://www.chenyudong.com/archives/java-web-struts-url-rewrite.html

分类: 网站建设

struts里不能获得request的参数

文章标题说不能从parameter中获得参数有点言过其实了,只是在不能使用某种方式来获得参数值。

最近在写一个系统,使用了struts2+spring+hibernate的架构。为了将jsp的页面进行模块化,将相同的部分抽取出来,形成一个单独的文件。然后使用strtus的<s:include>标签导入相同的文章。

示例demo,一个newPost.jsp,一个ajax/post.jsp,我们要在某个目录下添加文章,假设访问url:/newPost.jsp?category=2

<div id="contentDiv">
    <s:property value="#request[category]"/><!-- 显示2 -->
    <s:include value="admin-sidemenu.jsp">
        <s:param name="activeItem"  value="%{'add-post'}"></s:param>
    </s:include>

    <!-- main -->
    <div id="mainDiv">
        <s:include value="ajax/post.jsp"></s:include>
    </div>
    <!-- main end -->

    <s:property value="#request[category]"/><!-- 不工作了 -->
</div>
<%@page import="com.opensymphony.xwork2.ognl.OgnlValueStack"%>
<%    ((OgnlValueStack) request.getAttribute("struts.valueStack")).set(
            "activeItem", request.getParameter("activeItem"));
%>
<s:property value="activeItem"/><!-- 自己弄得valueStack这里能工作 -->
<s:property value="#request[category]"/><!-- 显示2 -->
<s:property value="#request.category"/><!-- 显示2 -->
<s:action name="category!categorys"></s:action>
<s:select name="categoryID" list="#request.categorys"
    listKey="categoryID" listValue="categoryName" headerKey="0"
    headerValue="未分类" id="articleCategory" theme="simple"
    value="#request[category]"><!-- 不工作了 -->
</s:select>
    说明:
  1. newPost.jsp:4因为要在admin-sidemenu.jsp页面中高亮当前的菜单,所以需要向该页面传入参数,以确定需要高亮显示的菜单。
  2. newPost.jsp:9因为要在ajax/post.jsp页面中默认选中目录,所以使用了#request[category]来获得category的值。
  3. newPost.jsp:2为了验证#request[category]是否工作而设置的。结果显示2
  4. ajax.post.jsp:1这里能工作,显示2
  5. ajax.post.jsp:2这里能工作,显示2
  6. ajax.post.jsp:7这里不工作,不默认自己选中
  7. newPost.jsp:13为了验证#request[category]在这里是否工作。结果不显示

虽然在<s:include>使用<s:param>标签想admin-sidemenu.jsp页面传入参数,然后再admin-sidemenu.jsp取出参数苦恼了许多问题。经过多种尝试,找到了自己喜欢的解决方案,获取include的方法请查看获取struts2 include标签param参数

但是在newPost.jsp后来居然获取不到#request[category]的值了!此前能取值,而且在ajax/post.jsp中的select标签也不能正常工作了。正是奇怪。

应该是把admin-menu.jsp中弄了个自己的valueStack,搞得有点乱了。所以还是把这个去了吧,改用我自己喜欢的include方法传参数,取参数值。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: struts里不能获得request的参数 – https://www.chenyudong.com/archives/does-not-access-request-parameters-in-strust-include.html

分类: 网站建设

用junit对struts2 action和spring进行单元测试

对action和spring进行测试,就不用再开tomcat了,此方法就是模拟用户的http请求进行的,但是这个方法不能看页面的工作情况,但对action的测试足够了。

此测试方法参考了http://depressedprogrammer.wordpress.com/2007/06/18/unit-testing-struts-2-actions-spring-junit/ ,此方法在我的代码中不能正常工作,需要改动。

首先需要的jar文件:spring-test-3.05.RELEASE.jar、spring-core-3.1.5RELEASE.jar,文中并没有给出相关依赖jar包。

public class PersonAction extend ActionSupport {

  private int id;

  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String deletePerson() {
    ....
    return SUCCESS;
  }
}
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import junit.framework.TestCase;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.views.JspSupportServlet;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.ContextLoader;

import java.util.HashMap;

/**
 * @author Zarar Siddiqi
 */
public abstract class BaseStrutsTestCase extends TestCase {
    private static final String CONFIG_LOCATIONS = "file:WebRoot/WEB-INF/applicationContext.xml";
    private static ApplicationContext applicationContext;
    private Dispatcher dispatcher;
    protected ActionProxy proxy;
    protected static MockServletContext servletContext;
    protected static MockServletConfig servletConfig;
    protected MockHttpServletRequest request;
    protected MockHttpServletResponse response;

    public BaseStrutsTestCase(String name) {
        super(name);
    }

    /**
     * Created action class based on namespace and name
     * @param clazz Class for which to create Action
     * @param namespace Namespace of action
     * @param name Action name
     * @return Action class
     * @throws Exception Catch-all exception
     */
    @SuppressWarnings("unchecked")
    protected <T> T createAction(Class<T> clazz, String namespace, String name)
            throws Exception {

        // create a proxy class which is just a wrapper around the action call.
        // The proxy is created by checking the namespace and name against the
        // struts.xml configuration
        proxy = dispatcher.getContainer().getInstance(ActionProxyFactory.class).
                createActionProxy(
                namespace, name, null, true, false);

        // by default, don't pass in any request parameters
        proxy.getInvocation().getInvocationContext().
                setParameters(new HashMap());

        // do not execute the result after executing the action
        proxy.setExecuteResult(true);

        // set the actions context to the one which the proxy is using
        ServletActionContext.setContext(
                proxy.getInvocation().getInvocationContext());
        request = new MockHttpServletRequest();
        response = new MockHttpServletResponse();
        ServletActionContext.setRequest(request);
        ServletActionContext.setResponse(response);
        ServletActionContext.setServletContext(servletContext);
        return (T) proxy.getAction();
    }

    protected void setUp() throws Exception {
        if( applicationContext == null ) {
            // this is the first time so initialize Spring context
            servletContext = new MockServletContext();
            servletContext.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
                    CONFIG_LOCATIONS);
            applicationContext = (new ContextLoader()).initWebApplicationContext(servletContext);

            // Struts JSP support servlet (for Freemarker)
            new JspSupportServlet().init(new MockServletConfig(servletContext));
        }
        // Dispatcher is the guy that actually handles all requests.  Pass in
        // an empty. Map as the parameters but if you want to change stuff like
        // what config files to read, you need to specify them here.  Here's how to
        // scan packages for actions (thanks to Hardy Ferentschik - Comment 66)
        // (see Dispatcher's source code)
        HashMap params = new HashMap();
        params.put("actionPackages", "com.test.action");
        dispatcher = new Dispatcher(servletContext, params);
        dispatcher.init();
        Dispatcher.setInstance(dispatcher);
    }
}

文中第20行在我的myeclipse不能工作,本来按原文的方法是抛出FileNotFound异常,采用改为file:WebRoot/WEB-INF/applicationContext.xml来解决的。其中第87行需要改成自己的包名。

public class PersonActionTest extends BaseStrutsTestCase {

 /**
  * Invoke all interceptors and specify value of the action
  * class' domain objects directly.
  * @throws Exception Exception
  */
 public void testInterceptorsBySettingDomainObjects()
         throws Exception {
  PersonAction action = createAction(PersonAction.class,
                "/site", "deletePerson");
  action.setId(123);
  String result = proxy.execute();
  assertEquals(result, "success");
 }

 /**
  * Invoke all interceptors and specify value of action class'
  * domain objects through request parameters.
  * @throws Exception Exception
  */
 public void testInterceptorsBySettingRequestParameters()
                     throws Exception {
  createAction(PersonAction.class, "/site", "deletePerson");
  request.addParameter("id", "123");
  String result = proxy.execute();
  assertEquals(result, "success");
 }

 /**
  * Skip interceptors and specify value of action class'
  * domain objects by setting them directly.
  * @throws Exception Exception
  */
 public void testActionAndSkipInterceptors() throws Exception {
  PersonAction action = createAction(PersonAction.class,
                  "/site", "deletePerson");
  action.setId(123);
  String result = action.deletePerson();
  assertEquals(result, "success");
 }
}

自己编写testcase继承该类即可。按照这个格式编写测试用例。

另外的junit方法,查看http://developer.51cto.com/art/201108/282751.htm

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 用junit对struts2 action和spring进行单元测试 – https://www.chenyudong.com/archives/unit-testing-struts-2-actions-and-spring-using-junit.html

分类: 网站建设

获取struts2 include标签param参数

struts 2的标签中,有个<s:include>标签,这个标签能将其他页面给包含到本页面。使用这个语法,能将网页给模块化了。不用写一个长长的页面,将相同的部分给抽取出来,从而复用代码。

同时,我们也可以向要include进来的页面传入参数。在被include的页面中,我们可以读取。

向include传入参数

<s:include value="myJsp.jsp" />
<s:include value="myJsp.jsp">
   <s:param name="param1" value="value2" />
   <s:param name="param2" value="value2" />
</s:include>
<s:include value="myJsp.jsp">
   <s:param name="param1">value1</s:param>
   <s:param name="param2">value2</s:param>
</s:include>

取参数方法一:${param.ParamName}官方的唯一方法

在被include页中取出参数,在myJsp.jsp页面中,获得参数的方法就是${param.ParamName}。

<div>通过这样取出参数值${param.param1}</div>

对了,要获得参数必须使用param这个对象。根据官方的struts include document说明,只能通过${param.param1}这样取出,其他方法不能直接取出来,<s:property>标签不能取出参数。

注意:不要在<s:property>标签的属性里使用${}标记,${}能够在html代码中直接显示。如果需要,请查阅Expression Language (EL)

取参数方法二:利用request对象来传递

include传参数还是一样的方法。但是在取参数,使用里一些小技巧。

<% pageContext.setAttribute("myparam" , request.getParameter("param1")); %>           
<s:property value="#attr.myparam"/>

通过pageContext对象来设置参数,或者你也可以使用request对象来实现参数的设置。有点投机了,不过此方法只能取字符串?为什么我不能获得其他值呢?

取参数方法三:不用include传入参数,在外头定义约定变量

<s:set name="param1" value="#request.user" />
<s:include value="myJsp.jsp" />

此方法有点投机取巧了。没有经过include标签传入参数,但在外头定义一个变量,在myJsp.jsp页取得共同约定的变量也不错。这样,在myJsp.jsp页中可以使用struts标签,和正常的情况一样使用,用起来很方便。个人喜欢使用这个方法。

取参数方法四:自己设置valueStack

参考文章来源:http://blog.csdn.net/james_wu_shanghai/article/details/4034739

在myJsp.jsp页面中自己忘valueStack添加自己的值。

<%@page import="com.opensymphony.xwork2.ognl.OgnlValueStack"%>
<%
 ((OgnlValueStack) request.getAttribute("struts.valueStack")).set(
   "operation", request.getParameter("operation"));
%>

<s:property value="operation"/>

此方法本人也用过,能正常工作,但是在其他页面出现问题了,详情请查看struts里不能获得request的参数。立刻将此方法撤下了。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 获取struts2 include标签param参数 – https://www.chenyudong.com/archives/access-struts2-include-tag-parameter-in-another-jsp-page.html

分类: 网站建设

Copyright © 2017 东东东 陈煜东的博客 粤ICP备13059639号-1

SITEMAP回到顶部 ↑