已经毕业很长时间了,回过头来想想都不知道自己做了什么,由于每个公司要求的技能都不一样,对之前学习的东西都已经忘记的差不多了,突然觉得这样很不好,万一哪天有想法了,出去之后都不知道自己能干什么了,所以还是抽空把之前学习的东西再梳理一遍,当然了,不可能一次就能完全讲清楚的,因此打算做了一个系列。
下面就开始我们的系列之一Strtus2的开发环境搭建
需要的开发环境:
运行环境:jdk(1.6以上,我用的是1.7.0_45),
开发工具:Eclipse版本不做要求,能开发就行,
数据库:(我这里是oracle,11gR2),
服务器:tomcat(6以上,我用的是7.0.54)。
当然还需要从struts官网上下载对应的zip包,我用的struts的版本为struts-2.2.3,网上百度谷歌下都可以找到struts的官网的。
以上都准备好了的话,我们就开始我们的struts旅程吧。
1.获得需要的jar文件。
1)解压开你刚下载的struts2的zip包,在apps下面找struts2-blank.war这个文件,解压开之后,找到里面的WEB-INF文件下的lib目录(struts-2.2.3-all\struts-2.2.3\apps\struts2-blank\WEB-INF\lib),里面就是我们搭建一个struts2的基本工程需要的jar包了。
2)获得oracle的驱动包,途径有很多种,就不在解释了,当然如果你 用的不是oracle的话,需要找对应数据库的jar包哦,我本地装有Oracle,所以在我的电脑中(app\Administrator\product\11.2.0\dbhome_1\owb\wf\lib)可以找到一个名字为ojdbc14.jar的jar包。
3)标准标签库的jar包,这个在tomcat下可以找到哦(apache-tomcat-7.0.54\webapps\examples\WEB-INF\lib),相信大家应该都知道吧,本文要用他的目的就是做一个简单的登陆和查询功能,所以涉及这个jar包了。
2.在Eclipse中新建一个动态的web项目,把刚才所说的jar包都拷贝我们工程的lib目录下。
3.拷贝web.xml文件。
在你刚才解压开的struts2的zip下找到这个目录(struts-2.2.3-all\struts-2.2.3\src\apps\blank\src\main\webapp\WEB-INF),把里面的web.xml文件拷贝到工程的WEB-INF目录下。
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <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> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
4.拷贝struts.xml文件。
还是在你刚才解压开的struts2的zip下找到这个目录(struts-2.2.3-all\struts-2.2.3\src\apps\blank\src\main\resources),把里面一个文件名叫struts.xml的文件拷贝到你的工程的src目录下。并且把<struts>标签内的内容全部删掉。
<?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> </struts>
5.新建一个index.html文件在工程的WebContent下。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 你好 </body> </html>
6.右键运行此工程到tomcat上,控制台如果没有报错,并出现如下信息,则说明你的struts2的开发环境已经搭建成功了。
七月 20, 2014 7:54:24 下午 org.apache.catalina.core.AprLifecycleListener init 信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: D:\Program Files (x86)\Java\jre7\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files (x86)\Common Files\NetSarang;D:\app\Administrator\product\11.2.0\dbhome_1\bin;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;E:\study\Work\apache-maven-3.0.4\bin;D:\Program Files (x86)\Java\jdk1.7.0_45\bin;E:\study\Work\apache-ant-1.9.2-bin\apache-ant-1.9.2\bin;. 七月 20, 2014 7:54:24 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin 警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:Struts2-1' did not find a matching property. 七月 20, 2014 7:54:24 下午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-bio-8080"] 七月 20, 2014 7:54:24 下午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["ajp-bio-8009"] 七月 20, 2014 7:54:24 下午 org.apache.catalina.startup.Catalina load 信息: Initialization processed in 736 ms 七月 20, 2014 7:54:24 下午 org.apache.catalina.core.StandardService startInternal 信息: Starting service Catalina 七月 20, 2014 7:54:24 下午 org.apache.catalina.core.StandardEngine startInternal 信息: Starting Servlet Engine: Apache Tomcat/7.0.54 七月 20, 2014 7:54:26 下午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info 信息: Parsing configuration file [struts-default.xml] 七月 20, 2014 7:54:27 下午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info 信息: Unable to locate configuration files of the name struts-plugin.xml, skipping 七月 20, 2014 7:54:27 下午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info 信息: Parsing configuration file [struts-plugin.xml] 七月 20, 2014 7:54:27 下午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger info 信息: Parsing configuration file [struts.xml] 七月 20, 2014 7:54:27 下午 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["http-bio-8080"] 七月 20, 2014 7:54:27 下午 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["ajp-bio-8009"] 七月 20, 2014 7:54:27 下午 org.apache.catalina.startup.Catalina start 信息: Server startup in 2473 ms
最终的项目组成如下图:
好了,工程搭建好了,我们再来模拟一个小小的登陆和查询的功能吧。
新建一个登陆的页面index.jsp,如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${errInfo } <form action="login.action" method="post"> <p>账号:<input type="text" name="userId"/></p> <p>密码:<input type="password" name="userPwd"/></p> <p><input type="submit" value="登录"/></p> </form> </body> </html>
网页中其实就是一个简单的form表单,相对一般的servlet不同的是,我们提交的action(struts2中的叫法)的地址变成了login.action。此处的名字,我在后面的struts.xml中会提到为何此处要用这个名字。
还有一个EL表达式,也就是去当前和页面进行交互的对象中的一个属性值,这个属性值叫errInfo。
这个页面对应的“servlet”是哪个呢?我们就来写它,如下:
package com.fit.action; import com.fit.service.LoginService; public class LoginAction { private String userId; private String userPwd; private String errInfo; //action方法,返回值表示转向的视图逻辑名称 public String execute(){ boolean ok=new LoginService().checkUser(userId, userPwd); if(ok){ return "成功的地方"; }else{ errInfo="登录失败!"; return "失败的地方"; } } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserPwd() { return userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; } public String getErrInfo() { return errInfo; } public void setErrInfo(String errInfo) { this.errInfo = errInfo; } }
三个属性,加属性的set个get方法,以及一个execute方法。
我的“Servlet”写好了,但是我怎么让struts2知道我要调用这个类呢?并且如果调用到了,要执行哪个方法呢?
还记得我让你们拷贝的struts.xml吗?就在这里通知Struts的控制器(就是我让你们拷贝web.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="demo" extends="struts-default"> <!-- 这里的name就是页面调用的名字,只是少了.action而已,这个暂时是固定写法,记住就可以了 --> <action name="login" class="com.fit.action.LoginAction"> <!-- 上面的class的取值就是我刚才写的那个类的全路径,表示,页面提交的form表单将来通过name的取值找到这个类, 然后执行里面的execute方法,这里我没有特别指定要执行那个方法,因此执行的是默认的方法 --> <!-- 这里的result标签就是这个方法的返回要跳转的逻辑值 也就是和LoginAction中的execute方法的返回值匹配的 --> <result name="成功的地方" type="redirect">stus.action</result> <!-- 为什么上面有个type属性呢?就是通知浏览器我如果登陆成功就重定向到stus.action这个类中,这个重定向的使用跟struts2的工作机制有关 ,如果大家不懂重定向和请求转发,可以百度或者谷歌下--> <result name="失败的地方">index.jsp</result> </action> <action name="stus" class="com.fit.action.StudentAction" method="stuList"> <!-- 这里我就声明了我要调用这个类的stuList方法 --> <!--这里没有写name的属性,struts默认如果方法返回success,就走这个分支--> <result>stuList.jsp</result> <result name="error">error.jsp</result> </action> </package> </struts>
有什么不明白的可以看xml中的注释。当然了,图中名字叫stus的action标签,是我们用来查询数据用的,当成功登陆之后,就重定向到StudentAction这个action,并且执行stuList这个方法,如果成功了,则跳转到stuList.jsp这个页面。
下面看下StudentAction的代码(其实就是调用service中方法,并且返回成功或者失败):
package com.fit.action; import java.util.List; import com.fit.service.StudentService; public class StudentAction { private List stus; public String stuList(){ try { stus=new StudentService().getAllStus(); return "success"; } catch (Exception e) { e.printStackTrace(); return "error"; } } public List getStus() { return stus; } public void setStus(List stus) { this.stus = stus; } }
下面给出两个Action对应的Service类
package com.fit.service; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import oracle.jdbc.OracleTypes; import com.fit.bean.Student; public class StudentService { public List getAllStus() throws Exception { List list = new ArrayList(); Connection conn = null; CallableStatement cst = null; ResultSet rs = null; try { Class.forName("oracle.jdbc.OracleDriver"); conn = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:fitdemo", "myuser", "myuser"); String sql = "{call find_all_stus(?)}"; cst = conn.prepareCall(sql); cst.registerOutParameter(1, OracleTypes.CURSOR); cst.execute(); rs = (ResultSet) cst.getObject(1); while (rs.next()) { Student stu = new Student(); stu.setStuId(rs.getInt("stu_id")); stu.setStuName(rs.getString("stu_name")); list.add(stu); } return list; } finally { try { rs.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try { cst.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try { if (!conn.isClosed()) conn.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
页面输入密码和用户校验的service(是假的,没有去数据库进行匹配,当然了我写的类中都是很简陋的,真实项目中可不是这样子的,这里只是举例)
package com.fit.service; public class LoginService { public boolean checkUser(String userId,String userPwd){ return "test".equals(userId)&&"123".equals(userPwd); } }
我想这个两个Service大家都能看懂吧,我为什么最原始的jdbc呢?是因为帮助大家回顾下,很多时候大家都用的开源的数据库访问框架,例如mybatis,hibernate啊之类的,对底层的东西可能都已经淡忘了,这里还用到了如何调用数据库的存储过程哦,如果对这方面不是很了解的话,可以普及下。
下面我就把这此工程涉及的表结构相关的sql展示下:
create table student( stu_id number primary key, stu_name varchar2(20) not null ); insert into student values(3,'学生3'); create or replace procedure find_all_stus (cur out sys_refcursor) is begin open cur for select * from student; end;
当然了,对应的JavaBean是必不可少的。
package com.fit.bean; public class Student { private int stuId; private String stuName; public int getStuId() { return stuId; } public void setStuId(int stuId) { this.stuId = stuId; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } }
截止现在,我已经大致的把整个工程的搭建给讲述了一遍,可能会有描述遗漏的地方,大家如果没有看懂的话,可以下载我附件中例子,然后修改下StudentService类中的关于数据库连接的信息,就可以查出来了,当然了,如果你不想要这段,想直接给一个list返回,也是没有问题的,我只是对数据库的访问和数据库的一些知识的串讲。
PS:这是本人第一次写文章,不是很专业,可能把大家都绕晕了,如果有什么疑问,可以直接留言问我,或者哪里有写的不对的地方,大家都可以指出来,共同学习嘛。
后续还有很多开源框架的文章,希望自己在写作上面能有很好的进步吧。