您的位置:首页 > 编程语言 > Java开发

Struts2学习总结(1)--基本原理,开发步骤,配置详解

2016-12-07 11:49 429 查看
本文包括以下三个部分:

模拟Struts2框架,了解基本原理。
Struts2的开发步骤。
Struts2的配置详解

一、模拟Struts2框架,了解基本原理

在学习Struts2框架以前,我们一直采用servlet进行网站的开发。最开始是一个功能使用一个servlet程序;后来创建BaseServlet进行简化,可以实现一个模块使用一个servlet程序;为了开发更加快捷,代码更加简洁,达到一个项目只使用一个servlet程序的目的,我们可以模拟一个简易的Struts2框架,并在此基础上了解Struts2的基本原理。

具体步骤如下:

1、创建一个模拟用户等录和注册的项目。



2、编写entity包代码。

User.Java

[html] view
plain copy

print?

package edu.scut.entity;

//用户

public class Users {

private int id;

private String name;

private String password;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public Users() {

super();

// TODO Auto-generated constructor stub

}

public Users(int id, String name, String password) {

super();

this.id = id;

this.name = name;

this.password = password;

}

@Override

public String toString() {

return "Users [id=" + id + ", name=" + name + ", password=" + password

+ "]";

}

}

3、编写dao层代码。

UserDao.java

[java] view
plain copy

print?

package edu.scut.dao;

import edu.scut.entity.Users;

public class UserDao {

//查询用户

public Users findByName(String name){

Users users = null;

if("jack".equals(name)){

users = new Users(1,"jack","666666");

}

return users;

}

//添加用户

public void addUser(Users users){

System.out.println("注册成功! "+users);

}

}

4、编写service层代码。

UserService.java

[html] view
plain copy

print?

package edu.scut.service;

import edu.scut.dao.UserDao;

import edu.scut.entity.Users;

import edu.scut.exception.LoginFailureException;

public class UserService {

UserDao userDao = new UserDao();

//登录

public Users Login(Users users) throws LoginFailureException{

Users loginUsers = userDao.findByName(users.getName());

//判断name

if(loginUsers == null){

throw new LoginFailureException("用户不存在!");

}

//判断密码

if(!loginUsers.getPassword().equals(users.getPassword())){

throw new LoginFailureException("密码错误!");

}

return loginUsers;

}

//注册

public void Reg(Users users){

userDao.addUser(users);

}

}

5、编写exception包代码。

LoginFailureException.java

[html] view
plain copy

print?

package edu.scut.exception;

public class LoginFailureException extends Exception {

public LoginFailureException() {

super();

// TODO Auto-generated constructor stub

}

public LoginFailureException(String message, Throwable cause) {

super(message, cause);

// TODO Auto-generated constructor stub

}

public LoginFailureException(String message) {

super(message);

// TODO Auto-generated constructor stub

}

public LoginFailureException(Throwable cause) {

super(cause);

// TODO Auto-generated constructor stub

}

}

6、编写web层代码。

UserAction.java

[java] view
plain copy

print?

package edu.scut.web;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import edu.scut.entity.Users;

import edu.scut.exception.LoginFailureException;

import edu.scut.service.UserService;

//用户模块的操作类

public class UserAction {

UserService userService = new UserService();

//URL:userLogin.action

public String login(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

String name = request.getParameter("name");

String password = request.getParameter("password");

//封装成对象

Users users = new Users();

users.setName(name);

users.setPassword(password);

try {

//调用登录方法

Users loginUsers = userService.Login(users);

//如果登录成功,将数据存储在域对象

request.getSession().setAttribute("loginInfo", loginUsers);

//主页

return "success";

} catch (LoginFailureException e) {

//如果登录失败,将信息存储在域对象

request.setAttribute("msg", e.getMessage());

return "fail";

}

}

//URL:userReg.action

public String reg(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//获取表单数据

String name = request.getParameter("name");

String password = request.getParameter("password");

//封装成对象

Users users = new Users();

users.setName(name);

users.setPassword(password);

//执行方法

userService.Reg(users);

//保存数据

request.setAttribute("regSuc", "注册成功,请登录!");

//跳转到登录页面

return "success";

}

}


7、编写配置文件mystruts.xml。

mystruts.xml

[html] view
plain copy

print?

<?xml version="1.0" encoding="UTF-8"?>

<struts>

<!-- 登录请求 -->

<!-- name:请求名称

class:执行的操作类类名

method:执行操作类的方法

-->

<action name="userLogin" className="edu.scut.web.UserAction" method="login">

<result name="fail" type="dispatcher">/login.jsp</result>

<result name="success" type="redirect">/index.jsp</result>

</action>

<!-- 注册请求 -->

<action name="userReg" className="edu.scut.web.UserAction" method="reg" >

<result name="success" type="dispatcher">/login.jsp</result>

</action>

</struts>

8、编写framework包代码。

8.1、编写Action的映射类即,ActionMapping.java

[java] view
plain copy

print?

package edu.scut.framework;

import java.util.List;

//action类

public class ActionMapping {

private String name;

private String className;

private String method;

private List<Result> results;

public List<Result> getResults() {

return results;

}

public void setResults(List<Result> results) {

this.results = results;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getClassName() {

return className;

}

public void setClassName(String className) {

this.className = className;

}

public String getMethod() {

return method;

}

public void setMethod(String method) {

this.method = method;

}

}

8.2、创建结果视图的类,即Result.java

[java] view
plain copy

print?

package edu.scut.framework;

//视图类型

public class Result {

private String name;

private String type;

private String path;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

}

8.3、编写ActionServlet.java,读取配置文件:mystruts.xml,UserAction的访问,以及结果视图的跳转。

[java] view
plain copy

print?

package edu.scut.framework;

import java.io.IOException;

import java.io.PrintWriter;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.management.RuntimeErrorException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2RTFDTM;

import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;

import edu.scut.web.UserAction;

public class ActionServlet extends HttpServlet {

//在Action初始化时就加载配置文件并且将其封装成对象

//创建Map集合封装actionMapping

Map<String, ActionMapping> actionMappings = null;

@Override

public void init() throws ServletException {

//创建actionMappings的实例

actionMappings = new HashMap<String, ActionMapping>();

try {

//读取mystruts.xml文件

SAXReader reader = new SAXReader();

//获取文件

Document doc = reader.read(ActionServlet.class.getResourceAsStream("/mystruts.xml"));

//获取根元素

Element root = doc.getRootElement();

//获取所有的action标签

List<Element> actionElements = (List<Element>)root.selectNodes("//action");

//遍历action集合

for (Element actionElement : actionElements) {

//获取属性值

String name = actionElement.attributeValue("name");

String className = actionElement.attributeValue("className");

String method = actionElement.attributeValue("method");

//创建actionMapping的对象

ActionMapping actionMapping = new ActionMapping();

actionMapping.setName(name);

actionMapping.setClassName(className);

actionMapping.setMethod(method);

//获取action当中的result对象

List<Element> resultElements = actionElement.elements("result");

//创建resultElements集合

List<Result> resultList = new ArrayList<Result>();

//遍历集合

for (Element resultElement : resultElements) {

//获取属性值

String resName = resultElement.attributeValue("name");

String resType = resultElement.attributeValue("type");

String resPath = resultElement.getText();

//创建Result对象

Result result = new Result();

result.setName(resName);

result.setType(resType);

result.setPath(resPath);

//封装进集合

resultList.add(result);

}

//将结果集封装进对象

actionMapping.setResults(resultList);

//将actionMapping封装进actionMappings集合

actionMappings.put(name, actionMapping);

System.out.println("mystruts.xml文件加载完毕!");

}

} catch (DocumentException e) {

//e.printStackTrace();

System.out.println("配置文件加载失败!");

throw new RuntimeException("配置文件读取失败!");

}

}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//url /userLogin.action

//1 得到路径 /day27_01_mystruts2_test/userLogin.action

String uri = request.getRequestURI();

//2 截取action的名字

String pathName = uri.substring(uri.lastIndexOf("/")+1, uri.lastIndexOf(".action"));

//3 根据action的名字获取className

ActionMapping actionMapping = actionMappings.get(pathName);

//创建一个变量接受返回值

String FURL = null;

try {

//4 根据action获取类名称

String className = actionMapping.getClassName();

//5 根据className创建实例

//获取字节码文件

Class clazz = Class.forName(className);

//创建对象

Object actionClass = clazz.newInstance();

//6 获取方法名称,调用响应的方法

String method = actionMapping.getMethod();

Method m = clazz.getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class);

//7 调用方法

FURL = (String) m.invoke(actionClass, request,response);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//8 根据返回值字符串返回响应的视图

List<Result> results = actionMapping.getResults();

//遍历集合

for (Result result : results) {

if(FURL.equals(result.getName())){

//获取返回视图的类型

String type = result.getType();

//获取返回视图的路径

String path = result.getPath();

//9 判断视图的类型执行响应的结果

if(type.equals("dispatcher")){

//转发

request.getRequestDispatcher(path).forward(request, response);

}else if(type.equals("redirect")){

//重定向

response.sendRedirect(request.getContextPath()+path);

}

}

}

//3 判断执行响应的方法

/*if("userLogin".equals(pathName)){

UserAction userAction = new UserAction();

userAction.login(request, response);

}else if("userReg".equals(pathName)){

UserAction userAction = new UserAction();

userAction.reg(request, response);

}*/

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

9、配置ActionServlet.java的访问路径。

web.xml

[html] view
plain copy

print?

<servlet>

<servlet-name>ActionServlet</servlet-name>

<servlet-class>edu.scut.framework.ActionServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>ActionServlet</servlet-name>

<url-pattern>*.action</url-pattern>

</servlet-mapping>

10、登录、注册和主页的jsp。

login.jsp:

[html] view
plain copy

print?

<body>

<font color="red">${msg}</font>

<form action="${pageContext.request.contextPath }/userLogin.action" method="post">

<%--<form action="${pageContext.request.contextPath }/users?action=login" method="post">--%>

用户名:<input type="text" name="name"><br>

密码:<input type="password" name="password"><br>

<input type="submit" value="登录"/>

</form>

</body>

reg.jsp:

[html] view
plain copy

print?

<body>

<form action="${pageContext.request.contextPath }/userReg.action" method="post">

<%-- <form action="${pageContext.request.contextPath }/users?action=reg" method="post">--%>

用户名:<input type="text" name="name"><br>

密码:<input type="password" name="password"><br>

<input type="submit" value="注册"/>

</form>

</body>

index.jsp:

[html] view
plain copy

print?

<body>

欢迎您,用户名:${sessionScope.loginInfo.name }

</body>

11、访问。

注册:http://localhost:8080/day27_01_mystruts2_test/reg.jsp

登录:http://localhost:8080/day27_01_mystruts2_test/login.jsp

访问之后的执行过程:

a. 创建ActionServlet实例;

b. 调用ActionServlet的init()方法;

c. 加载mystruts.xml配置文件,根据action的name找到对应的action,用反射的方式,创建UserAction的实例,再根据method的名称调用UserAction的同名方法;

d. 根据方法的返回值和result标签的name属性,找到result,实现页面跳转。

二、Struts2的开发步骤

1、导jar包。8个jar包。

2、配置struts2的核心过滤器。注意:在web.xml文件中配置,该核心过滤器用于处理项目的所有请求。

[html] view
plain copy

print?

<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、编写操作类。

[html] view
plain copy

print?

package edu.scut.web;

//用户操作类,表现层

public class UserAction {

//构造方法

public UserAction(){

System.out.println("useraction对象创建了!");

}

//userLogin.action

//登录方法

public String login(){

System.out.println("登录成功!");

return "success";

}

//userReg.action

public String reg(){

System.out.println("注册成功!");

return "success";

}

}

4、编写struts2的业务配置文件。 注意:名称一定为struts.xml,位置一定放在src目录下。

[html] view
plain copy

print?

<?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>

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

<!-- 登陆的action -->

<action name="userLogin" class="edu.scut.web.UserAction" method="login">

<result name="success" type="redirect">/index.jsp</result>

</action>

<!-- 注册的action -->

<action name="userReg" class="edu.scut.web.UserAction" method="reg">

<result name="success">/index.jsp</result>

</action>

</package>

</struts>

Struts2的执行过程:

a. 项目启动时:

1)加载web.xml文件,创建org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter核心过滤器对象

2)调用核心过滤器中的init方法

2.1 读取default.properties 【struts2的默认常量文件】

(struts2-core.jar: /org/apache/struts2/default.properties)

2.2 读取struts-default.xml 【struts2的默认核心配置文件】

(struts2-core.jar:/struts-default.xml)

2.3 读取struts-plugin.xml 【struts2的插入配置文件】

(一般不会用到)

2.4 读取struts.xml 【struts2的业务配置文件,开发时经常修改】

(项目的src:struts.xml)

b. 发出请求:

1)根据请求名称,在struts.xml文件中对应的action标签(根据action的name属性值)

2)查找结果

失败:

如果没有匹配成功,则页面抛出There is no Action mapped 异常

成功:

2.1 根据action标签的class的字符串去创建一个Action(操作)类实例

2.2 根据action标签的method去调用Action类里面对应的方法

2.3 执行完操作方法后,返回一个视图标记的字符串

3)根据视图标记字符串在当前action标签中查找对应的result标签(根据result的name属性值)

4)找到对应的result,则跳转到对应的页面

三、Struts2的配置详解

1、struts-default.xml : struts2的核心默认配置文件

第一部分:创建struts2框架自身需要的对象

<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />

。。。。。。

第二部分:一个默认包

<package name="struts-default" abstract="true">

name: 包名称

abstract: 抽象包

1) 定义struts2支持的视图类型

<result-types>

<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>

。。。。。

常用的视图类型:

dispatcher: 转发到页面 (默认类型) (可以通过request带数据)

redirect:重定向到页面

chain:转发到其他Action (可以通过request带数据)

redirectAction:重定向到其他Action

stream: 以流的形式进行输出 (用于文件下载)

plainText:以纯文本方法进行输出 (ajax技术)

2) 定义了struts2的支持的拦截器

<interceptors>

<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>

。。。。。。

struts2除了基本功能以外,还提供了如下实用功能:

传递页面参数数据

文件上传

国际化

数据共享

类型转换

表单数据校验

....

拦截器只能拦截action

过滤器可以拦截任何请求

3)定义了默认的拦截器栈

<interceptor-stack name="basicStack">

拦截栈中包含多个拦截器

4)定义当前包使用的默认拦截器

<default-interceptor-ref name="defaultStack"/>

当前包下的所有action都可以使用该拦截器栈下的所有拦截器

5)定义当前包的默认操作类

<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

当前包下的action如果不写class就使用默认类

2、 struts.xml: 业务配置文件

<package>:区分不用的action

name:包名。通常不同的包使用不同的名称(如果同名则报错)

extends:当前包的父包的包名。通常为struts-default默认包,继承了struts-default默认包就可以使用该包下定义的元素。

namespace: 名称空间(命名空间),为了区分不同包的访问路径。

注意:

有了namespace后,action的访问路径必须带上namespace。

<action> : 操作配置

name(必须): 请求名称,通常同一个包下不要出现同名的action。

class(可选): 操作类的全名(包+类名),默认类:com.opensymphony.xwork2.ActionSupport。

method(可选): 执行的操作方法,默认方法:execute。

<result> : 视图

name: 视图名称。跟操作方法返回的字符串匹配, 默认值:success。(其他名称都需要写)

type:视图类型, 默认值:dispatcher。

内容:跳转路径,如果是页面必须带斜杠,如果是action不需要。(没有默认值)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: