Java进阶学习第十五天(Struts框架)

版权声明:使用本品须Jack Gao同意,违者必究 https://blog.csdn.net/Mr_GaoYang/article/details/82693579

一、自定义一个Struts框架

1、MVC模式包括
Model:模型
View:视图
Control:控制器

2、传统mvc开发总结
① 跳转代码写死,不灵活
② 每次都去写servlet,要web.xml中配置servlet!

3、自定义一个Struts框架
① 配置文件mystruts.xml

<?xml version="1.0" encoding="UTF-8"?>
<mystruts>
	<package>
		<!-- 配置请求路径,与处理action类的关系,处理方法 -->
		<action name="login" class="cn.itcast.framework.action.LoginAction" method="login">
			<result name="loginSuccess" type="redirect">/index.jsp</result>
			<result name="loginFaild">/login.jsp</result>
		</action>
		
		<action name="register" class="cn.itcast.framework.action.RegisterAction" method="register">
			<result name="registerSuccess">/login</result>
			<result name="registerFaild">/login</result>
		</action>	
	</package>
</mystruts>

② ActionServlet.java

/**
 * 核心控制器,此项目只有这一个servlet
 * 1. 拦截所有的*.action为后缀的请求
 * 2. 请求:http://localhost:8080/mystruts/login.action
 * 		  http://localhost:8080/mystruts/register.action
 */
public class ActionServlet extends HttpServlet{
	private ActionMappingManager actionMappingManager;
	// 只执行一次,第一次访问时候执行  (希望启动时候执行)
	@Override
	public void init() throws ServletException {
		System.out.println("1111111111111111ActionServlet.init()");
		actionMappingManager = new ActionMappingManager();
	}

	// http://localhost:8080/mystruts/login.action
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		try {
			// 1. 获取请求uri, 得到请求路径名称   【login】
			String uri = request.getRequestURI();
			// 得到 login
			String actionName=uri.substring(uri.lastIndexOf("/")+1, uri.indexOf(".action"));
			// 2. 根据路径名称,读取配置文件,得到类的全名   【cn..action.LoginAction】
			ActionMapping actionMapping = actionMappingManager.getActionMapping(actionName);
			String className = actionMapping.getClassName();
			// 当前请求的处理方法   【method="login"】
			String method = actionMapping.getMethod();
			// 3. 通过反射:创建对象,调用方法;获取方法返回的标记
			Class<?> clazz = Class.forName(className);
			Object obj = clazz.newInstance();  //LoginAction loginAction = new LoginAction();
			Method m = clazz.getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class );
			// 调用方法返回的标记
			String returnFlag =  (String) m.invoke(obj, request, response);
			// 4. 拿到标记,读取配置文件得到标记对应的页面、跳转类型
			Result result = actionMapping.getResults().get(returnFlag);
			// 类型
			String type = result.getType();
			// 页面
			String page = result.getPage();
			// 跳转
			if ("redirect".equals(type)) {
				response.sendRedirect(request.getContextPath() + page);
			} else {
				request.getRequestDispatcher(page).forward(request, response);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

③ Result.java、ActionMapping.java、ActionMappingManager.java

/**
 * 封装结果视图
 * <result name="success" type="redirect">/index.jsp</result>
 */
public class Result {
	// 跳转的结果标记
	private String name;
	// 跳转类型,默认为转发;"redirect"为重定向
	private String type;
	// 跳转的页面
	private String page;
	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 getPage() {
		return page;
	}
	public void setPage(String page) {
		this.page = page;
	}
}
/**
 * 封装action节点
 *      <action name="login" class="cn.itcast.framework.action.LoginAction" method="login">
 *			<result name="success" type="redirect">/index.jsp</result>
 *			<result name="loginFaild">/login.jsp</result>
 *		</action>
 */
public class ActionMapping {
	// 请求路径名称
	private String name;
	// 处理aciton类的全名
	private String className;
	// 处理方法
	private String method;
	// 结果视图集合
	private Map<String,Result> 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;
	}
	public Map<String, Result> getResults() {
		return results;
	}
	public void setResults(Map<String, Result> results) {
		this.results = results;
	}
}
/**
 * 加载配置文件, 封装所有的整个mystruts.xml
 */
public class ActionMappingManager {
	// 保存action的集合
	private Map<String,ActionMapping> allActions ;
	public ActionMappingManager(){
		allActions = new HashMap<String,ActionMapping>();
		// 初始化
		this.init();
	}
	
	/**
	 * 根据请求路径名称,返回Action的映射对象
	 * @param actionName   当前请求路径
	 * @return             返回配置文件中代表action节点的AcitonMapping对象
	 */
	public ActionMapping getActionMapping(String actionName) {
		if (actionName == null) {
			throw new RuntimeException("传入参数有误,请查看mystruts.xml配置的路径。");
		}
		ActionMapping actionMapping = allActions.get(actionName);
		if (actionMapping == null) {
			throw new RuntimeException("路径在mystruts.xml中找不到,请检查");
		}
		return actionMapping;
	}
	
	// 初始化allActions集合
	private void init() {
		/********DOM4J读取配置文件***********/
		try {
			// 1. 得到解析器
			SAXReader reader = new SAXReader();
			// 得到src/mystruts.xml  文件流
			InputStream inStream = this.getClass().getResourceAsStream("/mystruts.xml");
			// 2. 加载文件
			Document doc = reader.read(inStream);
			// 3. 获取根
			Element root = doc.getRootElement();
			// 4. 得到package节点
			Element ele_package = root.element("package");
			// 5. 得到package节点下所有的action子节点
			List<Element> listAction = ele_package.elements("action");
			// 6.遍历 ,封装
			for (Element ele_action : listAction) {
				// 6.1 封装一个ActionMapping对象
				ActionMapping actionMapping = new ActionMapping();
				actionMapping.setName(ele_action.attributeValue("name"));
				actionMapping.setClassName(ele_action.attributeValue("class"));
				actionMapping.setMethod(ele_action.attributeValue("method"));
				// 6.2 封装当前aciton节点下所有的结果视图
				Map<String,Result> results = new HashMap<String, Result>();
				// 得到当前action节点下所有的result子节点
				 Iterator<Element> it = ele_action.elementIterator("result");
				 while (it.hasNext()) {
					 // 当前迭代的每一个元素都是 <result></result>
					 Element ele_result = it.next();
					 // 封装对象
					 Result res = new Result();
					 res.setName(ele_result.attributeValue("name"));
					 res.setType(ele_result.attributeValue("type"));
					 res.setPage(ele_result.getTextTrim());
					 // 添加到集合
					 results.put(res.getName(), res);
				 }
				// 设置到actionMapping中
				actionMapping.setResults(results);
				// 6.x actionMapping添加到map集合
				allActions.put(actionMapping.getName(), actionMapping);
			}			
		} catch (Exception e) {
			throw new RuntimeException("启动时候初始化错误",e);
		}
	}
}

④ LoginAction.java、RegisterAction.java

/**
 * Action表示动作类 1. 一个servlet对应一个action 2. action中负责处理具体的请求
 */
public class LoginAction {	
	public Object execute(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		return null;
	}

	/**
	 * 处理登陆请求
	 */
	public Object login(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Object uri = null;

		// 1. 获取请求数据,封装
		String name = request.getParameter("name");
		String pwd = request.getParameter("pwd");
		User user = new User();
		user.setName(name);
		user.setPwd(pwd);

		// 2. 调用Service
		UserService userService = new UserService();
		User userInfo = userService.login(user);
		// 3. 跳转
		if (userInfo == null) {
			// 登陆失败
			// request.getRequestDispatcher("/login.jsp").forward(request,response);
			// uri = request.getRequestDispatcher("/login.jsp");
			uri = "loginFaild";   // loginFaild  = /login.jsp
		} else {
			// 登陆成功
			request.getSession().setAttribute("userInfo", userInfo);
			// 首页
			// response.sendRedirect(request.getContextPath() + "/index.jsp");
			// uri = "/index.jsp";
			uri = "loginSuccess";  // loginSuccess = /index.jsp
		}
		return uri;
	}
}
public class RegisterAction {
	public Object register(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		Object uri;

		// 1. 获取请求数据,封装
		String name = request.getParameter("name");
		String pwd = request.getParameter("pwd");
		User user = new User();
		user.setName(name);
		user.setPwd(pwd);

		// 2. 调用Service
		UserService userService = new UserService();
		userService.register(user);
		// 3. 跳转
		// request.getRequestDispatcher("/login.jsp").forward(request, response);
		//uri = request.getRequestDispatcher("/login.jsp");
		return "registerSuccess"; //返回注册的标记;   registerSuccess = /login.jsp
	}
}

二、基于MVC模式的应用框架之Struts

1、Struts就是基于mvc模式的框架!
struts其实也是servlet封装,提高开发效率!

2、Struts开发步骤
① web项目,引入struts - jar包8个jar文件
② web.xml中,引入struts的核心功能配置过滤器

<!-- 引入struts核心过滤器 -->
	<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>

注意:如果引用其他拦截器一定要放在Struts拦截器上面
③ 开发action

// 开发action: 处理请求
public class HelloAction extends ActionSupport {
	// 处理请求
	public String execute() throws Exception {
		System.out.println("访问到了action,正在处理请求");
		System.out.println("调用service");
		return "success";
	}
}

④ 配置actionsrc/struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="xxxx" extends="struts-default">
    	<action name="hello" class="cn.itcast.action.HelloAction" method="execute">
    		<result name="success">/success.jsp</result>
    	</action>
    </package> 
</struts>

三、Struts框架学习

1、框架学习概述
SSH框架在mvc模式的的位置作用:
SSH

2、框架:
软件中的框架,是一种半成品; 我们项目开发需要在框架的基础上进行!
因为框架已经实现了一些功能,这样就可以提高开发效率!

3、Struts2框架
① Struts1最早的一种基于mvc模式的框架
② Struts2 是在Struts1的基础上,融合了xwork的功能
也可以说,Struts2 = struts1 + xwork

4、Struts2框架预先实现了一些功能:
① 请求数据自动封装
② 文件上传的功能
③ 对国际化功能的简化
④ 数据效验功能
……

5、Struts2(版本: 2.3)开发流程【重点】
① 引入jar文件
◆ commons-fileupload-1.2.2.jar 【文件上传相关包】
◆ commons-io-2.0.1.jar
◆ struts2-core-2.3.4.1.jar 【struts2核心功能包】
◆ xwork-core-2.3.4.1.jar 【Xwork核心包】
◆ ognl-3.0.5.jar 【Ognl表达式功能支持表】
◆ commons-lang3-3.1.jar 【struts对java.lang包的扩展】
◆ freemarker-2.3.19.jar 【struts的标签模板库jar文件】
◆ javassist-3.11.0.GA.jar 【struts对字节码的处理相关jar】
② 配置web.xml
Tomcat启动 > 加载自身web.xml > 加载所有项目的web.xml
通过在项目的web.xml中引入过滤器,Struts的核心功能的初始化,通过过滤器完成( filter 【init/ doFilter/ destroy】)

<!-- 引入struts核心过滤器 -->
	<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>

struts2-core-2.3.4.1.jar
StrutsPrepareAndExecuteFilter 即为核心过滤器
注意:使用的struts的版本不同,核心过滤器类是不一样的!
③ 开发Action
注意:
◆ action类,也叫做动作类,一般继承ActionSupport类,即处理请求的类 (struts中的action类取代之前的servlet)
◆ action中的业务方法,处理具体的请求( 必须返回String、方法不能有参数)

public class HelloAction extends ActionSupport {
	// 处理请求
	public String execute() throws Exception {}
}

④ 配置struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="xxxx" extends="struts-default">
    	<action name="hello" class="cn.itcast.action.HelloAction" method="execute">
    		<result name="success">/success.jsp</result>
    	</action>
    </package> 
</struts>

6、Struts2执行流程
① 服务器启动:
◆ 加载项目web.xml
◆ 创建Struts核心过滤器对象, 执行filter > init()
struts-default.xml:核心功能的初始化
struts-plugin.xml:struts相关插件
struts.xml:用户编写的配置文件
② 访问:
◆ 用户访问Action, 服务器根据访问路径名称,找对应的aciton配置,创建action对象
◆ 执行默认拦截器栈中定义的18个拦截器
◆ 执行action的业务处理方法

7、struts-default.xml 详解
① 目录:struts2-core-2.3.4.1.jar/ struts-default.xml
② 内容:
◆ bean节点指定struts在运行的时候创建的对象类型
◆ 指定struts-default包 【用户写的package(struts.xml)一样要继承此包 】
package:struts-default 包中定义了:
◇ 跳转的结果类型

	dispatcher      转发,不指定默认为转发
	redirect        重定向
	redirectAction  重定向到action资源
	stream          (文件下载的时候用)

◇ 定义了所有32个拦截器
为了拦截器引用方便,可以通过定义栈的方式引用拦截器,此时如果引用了栈,栈中的拦截器都会被引用!
defaultStack:默认的栈,其中定义默认要执行的18个拦截器(按顺序执行)!
默认执行的拦截器栈、默认执行的action

<default-interceptor-ref name="defaultStack"/>
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

8、拦截器(先睹为快):
拦截器功能与过滤器功能类似。
① 共同点: 都拦截资源!
② 区别 :
◆ 过滤器,拦截器所有资源都可以(/index.jsp/servlet/img/css/js)
◆ 拦截器,只拦截action请求。
◆ 拦截器是struts的概念,只能在struts中用。
◆ 过滤器是servlet的概念,可以在struts项目、servlet项目用。
③ 面试题: 拦截器什么时候执行? (访问/启动) 先执行action类创建,还是先执行拦截器?
答:用户访问时候按顺序执行18个拦截器;先执行Action类的创建,再执行拦截器; 最后拦截器执行完,再执行业务方法。

9、共性问题
① 问题1:Struts.xml配置文件没有提示
◆ 解决a:找到struts-2.0.dtd文件, 拷贝到某个目录(不要用中文目录),让MyEclipse关联到上面dtd文件(windows > preferences > 搜索xml catalog):

配置:
Location:上面配置的dtd目录
Key:-//Apache Software Foundation//DTD Struts Configuration 2.0//EN

◆ 解决b:让机器连接互联网,工具会自动下载dtd文件,缓存到MyEclipse中!
② 问题2
◆ 如果查看struts源码,需要关联源码包文件:struts-2.3.4.1-all
◆ 如果查看xwork源码,需要再单独下载xwork源码jar文件:xwork-core-2.3.4.1-sources,并再次关联

10、
① package:定义一个包,包的作用:管理action(通常一个业务模块用一个包)
② name:包的名字,包名不能重复
③ extends:当前包继承哪个包,在struts中,包一定要继承struts-default
struts-default是在struts-default.xml中定义的
④ abstract:表示当前包为抽象包,抽象包不能有action的定义,否则运行时会报错
只有当前包被其他包继承时,abstract=true
⑤ namespace:名称空间,默认为“/”,作为路径
⑥ action:配置请求路径与action类的映射关系(name请求路径名称,class请求处理action类全名,method请求处理方法)
⑦ result:name是action处理方法返回值,type是跳转的结果类型,标签体中指定跳转的界面

<struts>
    <package name="xxxx" extends="struts-default">
    	<action name="hello" class="cn.itcast.action.HelloAction" method="execute">
    		<result name="success">/success.jsp</result>
    	</action>
    </package> 
</struts>

猜你喜欢

转载自blog.csdn.net/Mr_GaoYang/article/details/82693579
今日推荐