转载请注明出处: http://qiudeqing.com/java_web/2016/01/07/struts2.html

Apache struts是开源java web MVC框架. 推荐约定优于配置.

配置struts2

本文使用Maven进行项目管理. 可以到struts2 maven archetypes查看不同的archetype然后直接获取配置好struts2不同功能的模板项目. 可以分别把这些archetype下载到本地查看各种配置. 本文手动创建一个webapp并配置struts2.

1. 创建符合Maven web project的基本项目结构

1) mkdir struts2-blank创建项目文件夹strtus2-blank, 后续的所有路径都是基于此

2) 创建pom.xml添加基本配置和插件

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.qiudeqing</groupId>
    <artifactId>struts2-blank</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>struts2-blank Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <finalName>struts2-blank</finalName>
        <plugins>
            <!-- Eclipse project -->
          <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-eclipse-plugin</artifactId>
          <version>2.9</version>
          <configuration>
                  <!-- Always download and attach dependencies source code -->
            <downloadSources>true</downloadSources>
            <downloadJavadocs>false</downloadJavadocs>
            <!-- Avoid type mvn eclipse:eclipse -Dwtpversion=2.0 -->
            <wtpversion>2.0</wtpversion>
          </configuration>
          </plugin>

          <!-- Set JDK Compiler Level -->
          <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.3.2</version>
          <configuration>
            <source>${jdk.version}</source>
            <target>${jdk.version}</target>
          </configuration>
          </plugin>

          <!-- For Maven Tomcat Plugin -->
          <plugin>
          <groupId>org.apache.tomcat.maven</groupId>
          <artifactId>tomcat7-maven-plugin</artifactId>
          <version>2.2</version>
          <configuration>
            <path>/</path>
            <uriEncoding>UTF-8</uriEncoding>
          </configuration>
          </plugin>
        </plugins>
    </build>
</project>

3) 创建src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      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>struts-blank</display-name>

    <welcome-file-list>
        <welcome-file>/public/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

4) 创建src/main/webapp/public/index.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<% request.setCharacterEncoding("UTF-8");%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no">
    <title>struts blank</title>
</head>
<body>
    <h2>struts blank</h2>
</body>
</html>

5) 命令行执行mvn tomcat7:run, 浏览器访问http://localhost:8080/页面显示struts blank. 基础java web项目结构创建成功

2. 添加struts2配置

1) pom.xml添加struts2和log4j2依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <struts2.version>2.3.24.1</struts2.version>
    <log4j2.version>2.3</log4j2.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-core</artifactId>
        <version>${struts2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
</dependencies>

2) 在src/main/webapp/WEB-INF/web.xml内添加struts2 filter

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3) 新建src/main/java/com/qiudeqing/action/HelloAction.java


package com.qiudeqing.action;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport {
    public String execute() throws Exception {
        return Action.SUCCESS;
    }
}

4) 添加src/main/resources/log4j2.xml


<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="com.opensymphony.xwork2" level="info"/>
        <Logger name="org.apache.struts2" level="info"/>
        <Root level="warn">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

5) 添加src/main/resources/struts.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>

    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />

    <package name="default" namespace="/" extends="struts-default">
        <action name="hello" class="com.qiudeqing.action.HelloAction" method="execute">
            <result>/public/hello.jsp</result>
        </action>
    </package>

</struts>

6) 添加src/main/webapp/public/hello.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no">
    <title>Document</title>
</head>
<body>
<h2>hello action with struts2</h2>
</body>
</html>

7) 命令行运行mvn tomcat7:run浏览器访问http://localhost:8080/hello显示hello action with struts2. web app集成struts2成功.

struts2 使用velocity作为模板引擎

velocity是一个java模板引擎, struts2默认支持velocity渲染结果.

struts2中配置velocity

1) 添加velocity依赖包

<!-- begin: velocity所依赖的包 -->
<!--
  velocity-tools依赖的某个包没有正确设置这个包的scope
  导致它输出到lib目录造成错误, 明确声明scope防止输出到lib
-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.3</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity</artifactId>
  <version>1.7</version>
</dependency>
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-tools</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>commons-beanutils</groupId>
  <artifactId>commons-beanutils</artifactId>
  <version>1.7.0</version>
</dependency>
<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.2</version>
</dependency>
<dependency>
  <groupId>commons-digester</groupId>
  <artifactId>commons-digester</artifactId>
  <version>1.8</version>
</dependency>
<dependency>
  <groupId>commons-lang</groupId>
  <artifactId>commons-lang</artifactId>
  <version>2.2</version>
</dependency>
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.1</version>
</dependency>
<dependency>
  <groupId>oro</groupId>
  <artifactId>oro</artifactId>
  <version>2.0.8</version>
</dependency>
<!-- end: velocity所依赖的包 -->

2) 修改src/main/java/com/qiudeqing/action/HelloAction.java添加属性name

package com.qiudeqing.action;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport {
    private String name;
    public String execute() throws Exception {
        name = "qiu <strong>deqing</strong>";
        return Action.SUCCESS;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

3) 到web.xml添加velocity Servlet

<servlet>
    <servlet-name>velocity</servlet-name>
    <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class>
    <init-param>
        <param-name>org.apache.velocity.properties</param-name>
        <param-value>velocity.properties</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>velocity</servlet-name>
    <url-pattern>*.vm</url-pattern>
</servlet-mapping>

4) 新建src/main/resources/velocity.properties

以下内容设置模板输入输出编码为UTF-8, 避免中文乱码

output.encoding=UTF-8
input.encoding=UTF-8
default.contentType=text/html; charset=UTF-8

5) 新建src/main/webapp/public/hello.vm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no">
    <title>Document</title>
</head>
<body>
<h2>转义的name: $esc.html($name)</h2>
<h2>没有转义的name: $name</h2>
</body>
</html>

6) src/main/resources/struts.xml中配置action

<action name="hello" class="com.qiudeqing.action.HelloAction" method="execute">
    <result>/public/hello.vm</result>
</action>

7) 命令行执行mvn tomcat7:run, 浏览器访问http://localhost:8080/hello显示

转义的name: qiu <strong>deqing</strong>

没有转义的name: qiu deqing

8) struts2 集成velocity成功

可以直接使用velocity generic tools

异常处理

全局异常处理

全局异常处理可以处理未捕获的异常. 在struts.xml中为package进行全局异常处理配置, 当包下面的某个action没有处理Exception时会自动使用默认异常处理

1) 修改src/main/java/com.qiudeqing.action.HelloAction.java添加error方法,抛出异常

package com.qiudeqing.action;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport {
    private String name;
    public String execute() throws Exception {
        name = "qiu <strong>deqing</strong>中文";
        return Action.SUCCESS;
    }
    public String error() throws Exception {
        throw new Exception();
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2) 添加src/main/webapp/public/error/error.vm作为异常显示页面

error page

3) 在src/main/resources/struts.xml中为package配置全局异常处理result以及error action

<package name="default" namespace="/" extends="struts-default">

    <global-results>
        <result name="error">/public/error/error.vm</result>
    </global-results>
    <global-exception-mappings>
        <exception-mapping exception="java.lang.Exception" result="error"></exception-mapping>
    </global-exception-mappings>

    <action name="error" class="com.qiudeqing.action.HelloAction" method="error">
    </action>
</package>

4) 启动服务器, 访问http://localhost:8080/error显示如下内容表示配置成功

error page

调试

struts2调试插件

调试插件可以列出各个action的详细配置信息, 方便查看是否遗漏

1) 在pom.xml中添加插件依赖

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-config-browser-plugin</artifactId>
    <version>${struts2.version}</version>
</dependency>

2) 启动服务器访问http://localhost:8080/config-browser/actionNames.action可以查看项目的配置信息

使用Debugging Interceptor查看action状态

如果struts配置devMode为true, 会启动一个DebuggingInterceptor

通过url传递参数debug即可显示访问的action状态, 如

http://localhost:8080/hello?debug=browser

debug可选值有xml, console, command, browser`

使用log查看调试信息

只需要在log4j2.xml中配置级别为debug即可查看struts2输出的详细调试信息

FAQs

jsp文件保存为UTF-8编码还是有中文乱码

添加jsp, html指令指明文件编码为UTF-8:

<%@ page contentType="text/html; charset=UTF-8" %>
<% request.setCharacterEncoding("UTF-8");%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no">
    <title>Document</title>
</head>
<body>
<form action="register">
    <input type="text" name="personBean.firstName" value="qiu">
    <input type="text" name="personBean.lastName" value="deqing">
    <input type="text" name="personBean.email" value="qiu@qiudeqing.com">
    <input type="text" name="personBean.age" value="27">
    <button type="submit">提交</button>
</form>
</body>
</html>

form提交中文到后端为乱码

方法1: 设置表单method=post

<form action="register" method="post">
    <input type="text" name="personBean.firstName" value="中文">
    <button type="submit">提交</button>
</form>

方法2: 设置tomcat URIEncoding="UTF-8"

不可能所有method都用get, 中文乱码的原因是get请求的参数是添加在url上的, struts2拦截器不会对url参数进行拦截并转换. tomcat默认url编码是iso-8859-1所以就出错了.在tomcat目录下conf/server.xml配置Connector添加URIEncoding="UTF-8"

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"/>

这样get请求的中文也不会乱码了.