自定义MVC框架(二) -基于XML文件
1.oracle的脚本
1 create table STUDENT 2 ( 3 sid NUMBER primary key, 4 sname VARCHAR2(20), 5 age NUMBER, 6 pwd VARCHAR2(20) 7 ) 8 9 create sequence seq_student; 10 11 insert into STUDENT (sid, sname, age, pwd) 12 values (seq_student.nextval, 'holly', 18, '123'); 13 insert into STUDENT (sid, sname, age, pwd) 14 values (seq_student.nextval, '钱涛', 108, '123'); 15 insert into STUDENT (sid, sname, age, pwd) 16 values (seq_student.nextval, '张睿', 10, '123'); 17 insert into STUDENT (sid, sname, age, pwd) 18 values (seq_student.nextval, '修地', 16, '123'); 19 commit;
2.创建如下的项目结果
(并在WebRoot下的lib文件夹下添加dom4j-1.6.1.jar和ojdbc14.jar)
3.在com.javabean包下创建Student.java文件
1 package com.javabean; 2 /** 3 * 学生类 4 * @author Holly老师 5 * 6 */ 7 public class Student { 8 /*学生编号*/ 9 private int sid; 10 /*学生姓名*/ 11 private String sname; 12 /*学生密码*/ 13 private String pwd; 14 /*年龄*/ 15 private int age; 16 17 public Student() { 18 super(); 19 } 20 21 public Student(int sid, String sname, String pwd, int age) { 22 super(); 23 this.sid = sid; 24 this.sname = sname; 25 this.pwd = pwd; 26 this.age = age; 27 } 28 29 public Student(int sid, String sname, int age) { 30 super(); 31 this.sid = sid; 32 this.sname = sname; 33 this.age = age; 34 } 35 36 public int getSid() { 37 return sid; 38 } 39 40 public void setSid(int sid) { 41 this.sid = sid; 42 } 43 44 public String getSname() { 45 return sname; 46 } 47 48 public void setSname(String sname) { 49 this.sname = sname; 50 } 51 52 public int getAge() { 53 return age; 54 } 55 56 public void setAge(int age) { 57 this.age = age; 58 } 59 60 public String getPwd() { 61 return pwd; 62 } 63 64 public void setPwd(String pwd) { 65 this.pwd = pwd; 66 } 67 68 69 }
4.在com.dao包下创建BaseDao.java
package com.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * 链接数据库的工具类 * @author Holly老师 */ public class BaseDao { /**链接数据库的字符串*/ private static final String driver="oracle.jdbc.driver.OracleDriver"; private static final String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl"; private static final String user="holly"; private static final String password="sys"; /**数据库操作的对象*/ public Connection conn=null; public PreparedStatement pstm=null; public ResultSet rs=null; /** * 加载驱动 */ static{ try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取数据库链接 * @return */ public Connection getConnection(){ try { conn=DriverManager.getConnection(url, user, password); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } /** * 查询公共方法 * @param sql * @param param * @return */ public ResultSet executeQuery(String sql,Object[] param){ conn=this.getConnection(); try { pstm=conn.prepareStatement(sql); if(param!=null){ for (int i = 0; i < param.length; i++) { pstm.setObject(i+1, param[i]); } } rs=pstm.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } return rs; } /** * 增删改通用方法 * @param sql * @param param * @return */ public int executeUpdate(String sql,Object[] param){ conn=this.getConnection(); int num=0; try { pstm=conn.prepareStatement(sql); if(param!=null){ for (int i = 0; i < param.length; i++) { pstm.setObject(i+1, param[i]); } } num=pstm.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally{ this.closeAll(conn, pstm, rs); } return num; } /** * 释放资源 * @param conn * @param pstm * @param rs */ public void closeAll(Connection conn,PreparedStatement pstm,ResultSet rs){ try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(pstm!=null){ pstm.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(conn!=null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
5.在com.dao包下创建StudentDao.java
1 package com.dao; 2 3 4 import com.javabean.Student; 5 /** 6 * 7 * @author Holly老师 8 * 9 */ 10 public interface StudentDao { 11 /** 12 * 根据用户名和密码查询 13 * @param sname 14 * @param pwd 15 * @return 16 */ 17 Student getByNameAndPwd(String sname,String pwd); 18 19 }
6.在com.dao.impl包下创建StudentDaoImpl.java
1 package com.dao.impl; 2 3 import java.sql.SQLException; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import com.dao.BaseDao; 8 import com.dao.StudentDao; 9 import com.javabean.Student; 10 /** 11 * 12 * @author Holly老师 13 * 14 */ 15 public class StudentDaoImpl extends BaseDao implements StudentDao { 16 /** 17 * 根据用户名和密码查询 18 * @param sname 19 * @param pwd 20 * @return 21 */ 22 public Student getByNameAndPwd(String sname,String pwd) { 23 Student stu=null; 24 String sql="select * from student where sname=? and pwd=?"; 25 26 Object[] param={sname,pwd}; 27 rs=this.executeQuery(sql, param); 28 try { 29 while(rs.next()){ 30 stu=new Student( 31 rs.getInt("sid"), 32 rs.getString("sname"), 33 rs.getString("pwd"), 34 rs.getInt("age")); 35 } 36 } catch (SQLException e) { 37 e.printStackTrace(); 38 }finally{ 39 this.closeAll(conn, pstm, rs); 40 } 41 return stu; 42 } 43 44 45 46 }
7.在com.service包下创建StudentService.java
package com.service; import com.javabean.Student; /** * 服务器接口 * @author Holly老师 * */ public interface StudentService { Student loginUser(String name,String pwd); }
8.在com.service包下创建StudentServiceImp.java
package com.service.impl; import com.dao.StudentDao; import com.dao.impl.StudentDaoImpl; import com.javabean.Student; import com.service.StudentService; /** * * @author Holly老师 * */ public class StudentServiceImpl implements StudentService{ StudentDao dao=new StudentDaoImpl(); public Student loginUser(String name, String pwd) { return dao.getByNameAndPwd(name, pwd); } }
9.在src下创建mystruts.xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mystruts[ <!ELEMENT mystruts (actions)> <!ELEMENT actions (action*)> <!ELEMENT action (result*)> <!ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED > <!ELEMENT result (#PCDATA)> <!ATTLIST result name CDATA #IMPLIED redirect (true|false) "false" > ]> <mystruts> <actions> <!-- 登录 --> <action name="login" class="com.action.LoginAction"> <result name="success">page/index.jsp</result> <result name="input">page/login.jsp</result> </action> <!-- 注册 --> <action name="register" class="com.action.RegisterAction"> <result name="success">page/login.jsp</result> <result name="input">page/register.jsp</result> </action> </actions> </mystruts> <!-- (1) 声明DTD:<!doctype 根元素 [定义内容]> (2)定义DTD元素标签节点 :<!ELEMENT 标签名称 元素类型> (3)定义DTD元素标签属性:<!ATTLIST 元素名称 属性名称 属性类型 属性默认值> ELEMENT 定义标签节点 ATTLIST 定义标签的属性 CDATA 表示属性类型是字符数据 #REQUIRED 属性值是必须的 #IMPLIED 属性值不是必须的 #FIXED 属性值是固定的 ()给元素分组 A|B 必须选择A或B A,B A和B按顺序出现 A* A出现0到n次 A? A出现0到1次 A+ A出现一次或n次 -->
10.在com.action包下创建Action.java
1 package com.action; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 /** 6 * 7 * @author Holly老师 8 * 9 */ 10 public interface Action { 11 /** 12 * 返回处理结果 13 * @param request 请求 14 * @param response 响应 15 * @return 失败或成功页面的字符串 16 * @throws Exception 17 */ 18 String execute(HttpServletRequest request, 19 HttpServletResponse response) throws Exception; 20 21 }
11.在com.action包下创建LoginAction.java
package com.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.javabean.Student; import com.service.StudentService; import com.service.impl.StudentServiceImpl; /** * * @author Holly老师 * */ public class LoginAction implements Action { /** * 处理请求返回处理结果 */ public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { //1.处理乱码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); //2.获取请求中的参数 String name=request.getParameter("user"); String pwd=request.getParameter("pwd"); //3.业务处理 StudentService service=new StudentServiceImpl(); Student stu=service.loginUser(name, pwd); //4.业务判断 if(stu!=null){ HttpSession session=request.getSession(); session.setAttribute("stu", stu); return "success"; }else{ return "input"; } } }
12.在com.mapper包下创建ActionMapping.java
package com.mapper; import java.util.HashMap; import java.util.Map; /** * Action节点的映射类 * @author Holly老师 * */ public class ActionMapping { /**action节点的name属性*/ private String name; /**action节点的class属性*/ private String className; /**保存配置的result属性*/ private Map<String,String> resultMap=new HashMap<String,String>(); /** * 通过result-name属性,返回对应的某个result节点 * @param name * @return */ public String getResult(String name){ return resultMap.get(name); } /** *在Map添加result节点=一个view*/ public void addResult(String name,String result){ this.resultMap.put(name, result); } 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 Map<String, String> getResultMap() { return resultMap; } public void setResultMap(Map<String, String> resultMap) { this.resultMap = resultMap; } }
13.在com.mapper包下创建
package com.mapper; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * Action的管理类 * @author Holly老师 * */ public class ActionMappingManager { /**map里放入多个action节点,key是action的name属性值, * value是整个的action节点,也就是action映射类ActionMapping*/ private static Map<String,ActionMapping> actionMappings =new HashMap<String,ActionMapping>(); /** * init方法加载action的配置信息 * @param configureFileName 配置文件的名字 */ public void init(String configureFileName){ try { if(configureFileName==null ||configureFileName.isEmpty()){ throw new Exception("configureFileName为空"); } //1.获取配置文件信息 InputStream is=this.getClass().getResourceAsStream("/"+configureFileName); //2.读取xml文件内容 Document doc=new SAXReader().read(is); //3.获取xml文件的根节点 Element root=doc.getRootElement(); //4.获取根节点mystrusts的下的所有actions节点 Iterator<Element> actionsIt=root.elements("actions").iterator(); //5.获取第一个actions节点 Element actions=actionsIt.next(); //6.获取actions下的所有action节点 Iterator<Element> actionIt=actions.elementIterator("action"); //7.循环取出action while(actionIt.hasNext()){ //取出下一个action Element action=actionIt.next(); //创建action对应映射类ActionMapping对象 ActionMapping mapping=new ActionMapping(); //将action节点的name属性值赋值给ActionMapping映射类的name属性 mapping.setName(action.attributeValue("name")); //将action节点的class属性值赋值给ActionMapping映射类的className属性 mapping.setClassName(action.attributeValue("class")); //获取action节点下所有的result集合 Iterator<Element> resultIt=action.elementIterator("result"); //循环取得result节点内容 while(resultIt.hasNext()){ //取得下一个result节点 Element resultElement=resultIt.next(); //获取result节点上的name属性值 String name=resultElement.attributeValue("name"); //获取result开始标签和结束标签之间的文本=跳转的页面地址 String result=resultElement.getText(); if(name==null ||name.equals("")){ name="success"; } //在我们映射类里添加result节点 mapping.addResult(name, result); } //把整个action节点添加到action管理类的集合中 actionMappings.put(mapping.getName(), mapping); } } catch (Exception e) { e.printStackTrace(); } } /** * 通过构造方法来加载Action配置文件 * @param 配置文件名数组 */ public ActionMappingManager(String[] configureFileNames){ for (String configureFileName : configureFileNames) { init(configureFileName); } } /** * 根据actionName查询对应的ActionMapping实例 * @param actionName * @return * @throws Exception */ public ActionMapping getActionMappingByName(String actionName) throws Exception{ if(actionName==null || actionName.isEmpty()){ return null; } ActionMapping mapping=this.actionMappings.get(actionName); if(mapping==null){ throw new Exception("mapping为空:["+actionName+"]"); } return mapping; } public static Map<String, ActionMapping> getActionMappings() { return actionMappings; } public static void setActionMappings(Map<String, ActionMapping> actionMappings) { ActionMappingManager.actionMappings = actionMappings; } }
14.在com.action包下创建ActionManager.java
package com.action; /** * 通过反射获取某个Action的实例/对象 * @author Holly老师 * */ public class ActionManager { /** * 通过反射获取Class对象 * @param className action的名字 * @return Class对象 * @throws ClassNotFoundException */ public static Class loadClass(String className) throws ClassNotFoundException{ Class clazz=null; //通过反射Class对象 clazz=Class.forName(className); return clazz; } /** * 用来动态获取Action类对象 * @param className Action的名字 * @return */ public static Action createAction(String className){ try { //通过class对象动态创建对象 return (Action) loadClass(className).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } }
15.在com.filter包下创建ActionFilter.java
package com.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.action.Action; import com.action.ActionManager; import com.action.LoginAction; import com.mapper.ActionMapping; import com.mapper.ActionMappingManager; /** * * @author Holly老师 * */ public class ActionFilter implements Filter { //定义储存拦截器初始化参数的成员变量 private FilterConfig config=null; //创建action映射文件管理类对象 private ActionMappingManager mappingManager=null; /**资源回收*/ public void destroy() {} /**初始化方法:获取拦截器的参数*/ public void init(FilterConfig conf) throws ServletException { this.config=conf; //获取xml文件中的参数值,:mystruts.xml String conStr=config.getInitParameter("config"); String[] configFiles=null; if(conStr==null || conStr.isEmpty()){ configFiles=new String[]{"mystruts.xml"}; }else{ //拆分配置文件名称字符串 configFiles=conStr.split(","); } //向多个action管理类的构造中传入xml文件的名 mappingManager=new ActionMappingManager(configFiles); } /**过滤请求*/ public void doFilter(ServletRequest sr, ServletResponse sp, FilterChain chain) throws IOException, ServletException { //1.获取request和response对象 HttpServletRequest request=(HttpServletRequest) sr; HttpServletResponse response=(HttpServletResponse) sp; try { //获取整个action节点 ActionMapping mapping=this.getActionMapping(request); //通过反射获取Action对象 Action action=ActionManager.createAction(mapping.getClassName()); //获取action类里处理请求返回的字符串,result的name属性,success或fail等 String resultName=action.execute(request, response); //通过返回的reuslt的name属性值获取result开始标签和结束标签之间的文本,跳转的页面 String result=mapping.getResult(resultName); if(result==null){ return; } //页面跳转(重定向) response.sendRedirect(result); } catch (Exception e) { e.printStackTrace(); } } /** * 获取不同的Action * @return * @throws Exception */ public ActionMapping getActionMapping(HttpServletRequest request) throws Exception { //1.获取请求的uri地址:项目名/Xxx.action String uri=request.getRequestURI(); //2.获取上下文路径:项目名 String contextpath=request.getContextPath(); //3.获取Xxx.action,从某个位置截取到最后 String actionPath=uri.substring(contextpath.length()); //4.获取Action的名字:Xxx String actionName=actionPath.substring(1, actionPath.lastIndexOf('.')).trim(); //5.获取某个Action的name属性值key获取整个acton类节点对象 ActionMapping mapping=null; mapping=mappingManager.getActionMappingByName(actionName); return mapping; } }
16.在WebRoot下WEB-INF下编辑web.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <welcome-file-list> 8 <welcome-file>page/login.jsp</welcome-file> 9 </welcome-file-list> 10 <filter> 11 <filter-name>requestFilter</filter-name> 12 <!-- 拦截器的类路径 --> 13 <filter-class>com.filter.ActionFilter</filter-class> 14 <init-param> 15 <param-name>config</param-name> 16 <param-value>mystruts.xml</param-value> 17 </init-param> 18 </filter> 19 20 <filter-mapping> 21 <filter-name>requestFilter</filter-name> 22 <!-- 拦截所有以.action结尾的请求 --> 23 <url-pattern>*.action</url-pattern> 24 </filter-mapping> 25 </web-app>
17.在WebRoot下创建page文件夹并编辑login.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme() + "://" 5 + request.getServerName() + ":" + request.getServerPort() 6 + path + "/"; 7 %> 8 9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 10 <html> 11 <head> 12 <base href="<%=basePath%>"> 13 14 <title>My JSP 'index.jsp' starting page</title> 15 <meta http-equiv="pragma" content="no-cache"> 16 <meta http-equiv="cache-control" content="no-cache"> 17 <meta http-equiv="expires" content="0"> 18 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 19 <meta http-equiv="description" content="This is my page"> 20 <!-- 21 <link rel="stylesheet" type="text/css" href="styles.css"> 22 --> 23 </head> 24 25 <body> 26 <fieldset style="width: 400px"> 27 <legend> 28 登录 29 </legend> 30 <form action="login.action" method="post"> 31 <table> 32 <tr> 33 <td> 34 用户名: 35 </td> 36 <td> 37 <input type="text" name="user" /> 38 </td> 39 </tr> 40 <tr> 41 <td> 42 密码: 43 </td> 44 <td> 45 <input type="password" name="pwd" /> 46 </td> 47 </tr> 48 <tr> 49 <td> 50 <input type="submit" value="登录" /> 51 </td> 52 <td> 53 <input type="reset" value="重置" /> 54 </td> 55 </tr> 56 57 </table> 58 </form> 59 </fieldset> 60 </body> 61 </html>
18.在WebRoot下创建page文件夹并编辑index.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 %> 6 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 7 <html> 8 <head> 9 <base href="<%=basePath%>"> 10 11 <title>My JSP 'index.jsp' starting page</title> 12 <meta http-equiv="pragma" content="no-cache"> 13 <meta http-equiv="cache-control" content="no-cache"> 14 <meta http-equiv="expires" content="0"> 15 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 16 <meta http-equiv="description" content="This is my page"> 17 <!-- 18 <link rel="stylesheet" type="text/css" href="styles.css"> 19 --> 20 </head> 21 22 <body> 23 欢迎${stu.sname}登录首页! 24 </body> 25 </html>
19.写完了
自己测试一下