struts1的另一个简单例子(添加学生信息到数据库)

来源:互联网 发布:软件系统销售合同范本 编辑:程序博客网 时间:2024/06/01 15:00

马哥的淘宝店:https://shop592330910.taobao.com/

总结:

1.action什么时候初始化,也就是什么时候创建Action的对象?发出该action请求时创建实例对象。不是读配置时创建的。
2.每个action只会创建一个实例对象,也就是单例的。
3.action是线程不安全的,因为所有的请求共享一个action实例。

4.怎样实现action的安全编程:

注意不要用实例变量或者类变量来 共享 只 是针对某个请求的数据。
注意资源操作的同步性。


ActionMapping,ActionForward,ActionForm

action-mappings节点下面定义各个action节点。
action-mappings元素帮助进行框架内部流程控制,可将请求URI映射到Action类,
将Action对象与ActionForm相关联。
这个下面可以设置多个子节点action节点。

action节点,所描述的是特定的请求路径和一个相应的action类之间的映射关系。

<action-mappings>    <action path="/login" type="com.mamh.struts1.demo.action.LoginAction" name="loginForm" >        <forward name="loginSuccess" path="/loginSuccess.jsp"/>        <forward name="loginFailure" path="/loginFailure.jsp"/>    </action>    <action path="/addStudentAction" type="com.mamh.struts1.demo.action.AddStudentAction" name="addStudentForm">        <forward name="addSuccess" path="/addSuccess.jsp"/>        <forward name="addFailure" path="/addFailure.jsp"/>    </action></action-mappings>

execute()方法第一个参数就是ActionMapping对象,我们可以通过mapping获取到一些值。
其实获取的就是action-mappings节点下面的所有的配置内容。
getName() Return name of the form bean, if any, associated with this Action.

System.out.println("=====================================================");String name = mapping.getName();//addStudentFormString path = mapping.getPath();String type = mapping.getType();String[] forwards = mapping.findForwards();for(String fname: forwards){    System.out.println(fname);}System.out.println(name);// addStudentFormSystem.out.println(path);// //addStudentActionSystem.out.println(type);// com.mamh.struts1.demo.action.AddStudentActionSystem.out.println("=====================================================");

<forward name="loginFailure" path="/loginFailure.jsp" redirect="false"/>
这里的redirect默认是false,是表示转发。设置为true表示重定向。这个值可以有true,false,yes,no这四个。

全局跳转global-forwards,减少代码量,实现代码共享。

    <global-forwards>        <forward name="error" path="/error.jsp"/>    </global-forwards>

action节点下面的属性

<action path="/login" type="com.mamh.struts1.demo.action.LoginAction" name="loginForm" scope="request" >

validate=”true” 属性, 判断是否需要校验,用于是否校验。不校验就不会去调用validate()方法。这个值可以有true,false,yes,no这4个。默认是true。
input=”loginFailure.jsp”,该Action所引用的Form校验失败跳转到这个input对应的页面。跳转其实用的是转发的方式。一般结合validate=”true” 属性一起使用。
scope=”request” 属性, action节点可以设置一个作用范围:scope这个可以取值request,session中的1个。默认是session。
attribute=”addStudentForm” 属性,设置和Action关联的ActionForm在request,session内的属性key,通过request,session的getAttribute()方法返回该ActionForm实例。request.getSession().getAttribute("addStudentForm");代码中可以这样去取能不能通过这种方式获取到ActionForm关键是这个决定的。这个如果不设置默认去name的值。
name=”addStudentForm”属性,

查找action,看action中是否有name属性,scope属性,根据name和scope找到对应的ActionForm。

找到就用现成的ActionForm对象,如果没找到就新建ActionForm对象(实例化,并且存到相应的scope里面)。

调用ActionForm的reset()方法,复位。

取值(从客户参数,request.getParamter()取得参数,)和赋值(设置ActionForm属性,调用setter方法)。

如果action节点的validate设置了true就做校验,调用ActionForm的validate()方法。

校验成功,派发请求到相应的action。
校验失败,失败一般跳到错误页面。

执行相应的action的execute()方法。

先调用无参数的构造方法:AddStudentForm() construtor必须要有一个无参数的构造器!!!保存到相应的scope(request,session)中。我们可以通过一个 AttributeListener 来研究这个执行过程。然后调用reset()方法:public void reset(ActionMapping mapping, HttpServletRequest request)最后调用setter()之类的方法,setter方法调用顺序不重要的。    setBirth()    setName()    setScore()    setMajor()调用Action的execute()方法。
<form-beans>    <form-bean name="loginForm" type="com.mamh.struts1.demo.form.LoginForm" />    <form-bean name="addStudentForm" type="com.mamh.struts1.demo.form.AddStudentForm"/></form-beans>

在execute()方法中分析ActionForm
自己从session中取这个ActionForm对象和execute方法中那个参数form是一个对象的。是==的。

    @Override    public ActionForward execute(ActionMapping mapping, ActionForm form,                                 HttpServletRequest request, HttpServletResponse response) throws Exception {        System.out.println("AddStudentAction execute(");        AddStudentForm sessionForm = (AddStudentForm) request.getSession().getAttribute("addStudentForm");        AddStudentForm addStudentForm = (AddStudentForm) form;        System.out.println("sessionForm == addStudentForm   : "+ (sessionForm == addStudentForm));

对于调用的setter方法,这个方法名是和form表单中的相一至的。不关心属性名称是否一致。

比如form中有个<input type="text" name="name"/>就会调用setName()方法。
比如form中有个<input type="text" name="major"/>就会调用setMajor()方法。


下面看一个例子,添加学生信息到数据库

首先新建个AddStudentAction 的Action的子类,重写了execute()方法,
这个方法里面调用操作数据库的相关的业务逻辑代码,然后根据业务逻辑返回的
值来决定最后要转发到哪个页面。

public class AddStudentAction extends Action {    @Override    public ActionForward execute(ActionMapping mapping, ActionForm form,                                 HttpServletRequest request, HttpServletResponse response) throws Exception {        System.out.println("AddStudentAction execute(");        AddStudentForm addStudentForm = (AddStudentForm) form;        DAO studentDao = new StudentDAOImpl();        boolean addResult = studentDao.add(addStudentForm);        String url = "";        if (addResult) {            url = "addSuccess";        } else {            url = "addFailure";        }        return mapping.findForward(url);    }}

这里定义一个dao的接口

public interface DAO {    boolean add(AddStudentForm form);}

实现添加数据到student数据库表的StudentDAOImpl 类

public class StudentDAOImpl implements DAO {    public boolean add(AddStudentForm form) {        String sql = "insert into student(name,birth,major,score) values(?, ?, ?,?)";        JdbcUtils.update(sql, form.getName(), form.getBirth(), form.getMajor(), form.getScore());        return true;    }}

数据库相关的工具类方法

public class JdbcUtils {    /**     * 执行 SQL 语句, 使用 PreparedStatement     *     * @param sql     * @param args: 填写 SQL 占位符的可变参数     */    public static void update(String sql, Object... args) {        Connection connection = null;        PreparedStatement preparedStatement = null;        try {            connection = JdbcUtils.getConnection();            preparedStatement = connection.prepareStatement(sql);            for (int i = 0; i < args.length; i++) {                preparedStatement.setObject(i + 1, args[i]);            }            preparedStatement.executeUpdate();        } catch (Exception e) {            e.printStackTrace();        } finally {            JdbcUtils.release(null, preparedStatement, connection);        }    }    public static void release(Statement statement, PreparedStatement preparedStatement, Connection connection) {        //4.关闭statement        try {            if (statement != null)                statement.close();        } catch (SQLException e) {            e.printStackTrace();        }        //5.关闭数据库链接        try {            if (connection != null)                connection.close();        } catch (SQLException e) {            e.printStackTrace();        }    }    /**     * 编写一个通用的方法,在不修改源程序的情况下,可以获取任何数据库的链接     * 解决方法:把数据库驱动Driver的全类名,url,user,password放入到一个     * 配置文件中。     *     * @return     */    public static Connection getConnection() throws Exception {        //1. Class.getResourceAsStream(String path) :        // path 不以’/'开头时默认是从此类所在的包下取资源,        // 以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。        com.mysql.jdbc.Driver driver = null;        InputStream in = JdbcUtils.class.getResourceAsStream("/jdbc.prop");        Properties properties = new Properties();        properties.load(in);        String className = "com.mysql.jdbc.Driver";        String jdbcUrl = "jdbc:mysql://10.0.63.43/test";        String user = "test";        String password = "123456";        className = properties.getProperty("className");        jdbcUrl = properties.getProperty("jdbcUrl");        user = properties.getProperty("user");        password = properties.getProperty("password");        System.out.println("className = " + className);        System.out.println("jdbcUrl   = " + jdbcUrl);        System.out.println("user      = " + user);        System.out.println("password  = " + password);        Class.forName(className);        Connection c = DriverManager.getConnection(jdbcUrl, user, password);        return c;    }}

新建一个AddStudentForm 的类,继承ActionForm 。里面的属性名对应jsp页面表单中的input的name的值。

public class AddStudentForm extends ActionForm {    private String name = null;    private String major = null;    private String score = null;    private String birth = null;    public AddStudentForm() {        System.out.println("AddStudentForm(1) construtor!!!!!!!!!!");    }    @Override    public ActionErrors validate(ActionMapping mapping, ServletRequest request) {        System.out.println("    public ActionErrors validate(ActionMapping mapping, ServletRequest request) {");        return super.validate(mapping, request);    }    @Override    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {        System.out.println("    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {");        return super.validate(mapping, request);    }    @Override    public void reset(ActionMapping mapping, ServletRequest request) {        System.out.println("public void reset(ActionMapping mapping, ServletRequest request) ");        super.reset(mapping, request);    }    @Override    public void reset(ActionMapping mapping, HttpServletRequest request) {        System.out.println("public void reset(ActionMapping mapping, HttpServletRequest request)");        super.reset(mapping, request);    }    public String getName() {        return name;    }    public void setName(String name) {        System.out.println("setName()");        this.name = name;    }    public String getMajor() {        return major;    }    public void setMajor(String major) {        System.out.println("setMajor()");        this.major = major;    }    public String getScore() {        return score;    }    public void setScore(String score) {        System.out.println("setScore()");        this.score = score;    }    public String getBirth() {        return birth;    }    public void setBirth(String birth) {        System.out.println("setBirth()");        this.birth = birth;    }}

struts-config.xml 文件添加form-bean节点。同时添加action 节点。这个对应了上面的AddStudentForm,和AddStudentAction类

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC        "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"        "http://struts.apache.org/dtds/struts-config_1_2.dtd"><struts-config>    <form-beans>        <form-bean name="loginForm" type="com.mamh.struts1.demo.form.LoginForm" />        <form-bean name="addStudentForm" type="com.mamh.struts1.demo.form.AddStudentForm" />    </form-beans>    <action-mappings>        <action path="/login" type="com.mamh.struts1.demo.action.LoginAction" name="loginForm" >            <forward name="loginSuccess" path="/loginSuccess.jsp"/>            <forward name="loginFailure" path="/loginFailure.jsp"/>        </action>        <action path="/addStudentAction" type="com.mamh.struts1.demo.action.AddStudentAction" name="addStudentForm">            <forward name="addSuccess" path="/addSuccess.jsp"/>            <forward name="addFailure" path="/addFailure.jsp"/>        </action>    </action-mappings></struts-config>

web.xml 文件

<!DOCTYPE web-app PUBLIC        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"        "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app>    <display-name>Archetype Created Web Application</display-name>    <servlet>        <servlet-name>action</servlet-name>        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>        <init-param>            <param-name>config</param-name>            <param-value>/WEB-INF/struts-config.xml</param-value>        </init-param>        <load-on-startup>0</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>action</servlet-name>        <url-pattern>*.do</url-pattern>    </servlet-mapping></web-app>

添加学生信息的jsp,里面含有表单form。

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>addStudentAction</title></head><body><form action="/addStudentAction.do" method="post">    name: <label>    <input type="text" name="name"/></label>    <br/>    major: <label>    <input type="text" name="major"/></label>    <br/>    score: <label>    <input type="text" name="score"/></label>    <br/>    birth: <label>    <input type="text" name="birth"/></label>    <br/>    <input type="submit" value="add student"/></form></body></html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>addFailure.jsp</title></head><body><H1>add failure</H1></body></html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>addSuccess.jsp</title></head><body><H1>add success!!!!!!!!!!!!</H1></body></html>

用于研究ActionForm什么时候被设置到相应的scope中的。

public class AttributeListener implements        ServletRequestAttributeListener, HttpSessionAttributeListener {    public void attributeAdded(ServletRequestAttributeEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeAdded(ServletRequestAttributeEvent event) { name = " + name + " , value = " + value);    }    public void attributeRemoved(ServletRequestAttributeEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeRemoved(ServletRequestAttributeEvent event) { name = " + name + " , value = " + value);    }    public void attributeReplaced(ServletRequestAttributeEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeReplaced(ServletRequestAttributeEvent event) { name = " + name + " , value = " + value);    }    public void attributeAdded(HttpSessionBindingEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeAdded(HttpSessionBindingEvent event) { name = " + name + " , value = " + value);    }    public void attributeRemoved(HttpSessionBindingEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeRemoved(HttpSessionBindingEvent event) { name = " + name + " , value = " + value);    }    public void attributeReplaced(HttpSessionBindingEvent event) {        String name = event.getName();        Object value = event.getValue();        System.out.println("attributeReplaced(HttpSessionBindingEvent event) { name = " + name + " , value = " + value);    }}

下面介绍一些idea的技巧

Intellij IDEA中有很多快捷键让人爱不释手,stackoverflow上也有一些有趣的讨论。每个人都有自己的最爱,想排出个理想的榜单还真是困难。以前也整理过Intellij的快捷键,这次就按照我日常开发时的使用频率,简单分类列一下我最喜欢的十大快捷-神-键吧。1 智能提示Intellij首当其冲的当然就是Intelligence智能!基本的代码提示用Ctrl+Space,还有更智能地按类型信息提示Ctrl+Shift+Space,但因为Intellij总是随着我们敲击而自动提示,所以很多时候都不会手动敲这两个快捷键(除非提示框消失了)。用F2/ Shift+F2移动到有错误的代码,Alt+Enter快速修复(即Eclipse中的Quick Fix功能)。当智能提示为我们自动补全方法名时,我们通常要自己补上行尾的反括号和分号,当括号嵌套很多层时会很麻烦,这时我们只需敲Ctrl+Shift+Enter就能自动补全末尾的字符。而且不只是括号,例如敲完if/for时也可以自动补上{}花括号。最后要说一点,Intellij能够智能感知spring、hibernate等主流框架的配置文件和类,以静制动,在看似“静态”的外表下,智能地扫描理解你的项目是如何构造和配置的。2 重构Intellij重构是另一完爆Eclipse的功能,其智能程度令人瞠目结舌,比如提取变量时自动检查到所有匹配同时提取成一个变量等。尤其看过《重构-改善既有代码设计》之后,有了Intellij的配合简直是令人大呼过瘾!也正是强大的智能和重构功能,使Intellij下的TDD开发非常顺畅。切入正题,先说一个无敌的重构功能大汇总快捷键Ctrl+Shift+Alt+T,叫做Refactor This。按法有点复杂,但也符合Intellij的风格,很多快捷键都要双手完成,而不像Eclipse不少最有用的快捷键可以潇洒地单手完成(不知道算不算Eclipse的一大优点),但各位用过Emacs的话就会觉得也没什么了(非Emacs黑)。此外,还有些最常用的重构技巧,因为太常用了,若每次都在Refactor This菜单里选的话效率有些低。比如Shift+F6直接就是改名,Ctrl+Alt+V则是提取变量。3 代码生成这一点类似Eclipse,虽不是独到之处,但因为日常使用频率极高,所以还是罗列在榜单前面。常用的有fori/sout/psvm+Tab即可生成循环、System.out、main方法等boilerplate样板代码,用Ctrl+J可以查看所有模板。后面“辅助”一节中将会讲到Alt+Insert,在编辑窗口中点击可以生成构造函数、toString、getter/setter、重写父类方法等。这两个技巧实在太常用了,几乎每天都要生成一堆main、System.out和getter/setter。另外,Intellij IDEA 13中加入了后缀自动补全功能(Postfix Completion),比模板生成更加灵活和强大。例如要输入for(User user : users)只需输入user.for+Tab。再比如,要输入Date birthday = user.getBirthday();只需输入user.getBirthday().var+Tab即可。4 编辑编辑中不得不说的一大神键就是能够自动按语法选中代码的Ctrl+W以及反向的Ctrl+Shift+W了。此外,Ctrl+Left/Right移动光标到前/后单词,Ctrl+[/]移动到前/后代码块,这些类Vim风格的光标移动也是一大亮点。以上Ctrl+Left/Right/[]加上Shift的话就能选中跳跃范围内的代码。Alt+Forward/Backward移动到前/后方法。还有些非常普通的像Ctrl+Y删除行、Ctrl+D复制行、Ctrl+</>折叠代码就不多说了。关于光标移动再多扩展一点,除了Intellij本身已提供的功能外,我们还可以安装ideaVim或者emacsIDEAs享受到Vim的快速移动和Emacs的AceJump功能(超爽!)。另外,Intellij的书签功能也是不错的,用Ctrl+Shift+Num定义1-10书签(再次按这组快捷键则是删除书签),然后通过Ctrl+Num跳转。这避免了多次使用前/下一编辑位置Ctrl+Left/Right来回跳转的麻烦,而且此快捷键默认与Windows热键冲突(默认多了Alt,与Windows改变显示器显示方向冲突,一不小心显示器就变成倒着显式的了,冏啊)。5 查找打开类似Eclipse,Intellij的Ctrl+N/Ctrl+Shift+N可以打开类或资源,但Intellij更加智能一些,我们输入的任何字符都将看作模糊匹配,省却了Eclipse中还有输入*的麻烦。最新版本的IDEA还加入了Search Everywhere功能,只需按Shift+Shift即可在一个弹出框中搜索任何东西,包括类、资源、配置项、方法等等。类的继承关系则可用Ctrl+H打开类层次窗口,在继承层次上跳转则用Ctrl+B/Ctrl+Alt+B分别对应父类或父方法定义和子类或子方法实现,查看当前类的所有方法用Ctrl+F12。要找类或方法的使用也很简单,Alt+F7。要查找文本的出现位置就用Ctrl+F/Ctrl+Shift+F在当前窗口或全工程中查找,再配合F3/Shift+F3前后移动到下一匹配处。Intellij更加智能的又一佐证是在任意菜单或显示窗口,都可以直接输入你要找的单词,Intellij就会自动为你过滤。6 其他辅助以上这些神键配上一些辅助快捷键,即可让你的双手90%以上的时间摆脱鼠标,专注于键盘仿佛在进行钢琴表演。这些不起眼却是至关重要的最后一块拼图有:Ø  命令:Ctrl+Shift+A可以查找所有Intellij的命令,并且每个命令后面还有其快捷键。所以它不仅是一大神键,也是查找学习快捷键的工具。Ø  新建:Alt+Insert可以新建类、方法等任何东西。Ø  格式化代码:格式化import列表Ctrl+Alt+O,格式化代码Ctrl+Alt+L。Ø  切换窗口:Alt+Num,常用的有1-项目结构,3-搜索结果,4/5-运行调试。Ctrl+Tab切换标签页,Ctrl+E/Ctrl+Shift+E打开最近打开过的或编辑过的文件。Ø  单元测试:Ctrl+Alt+T创建单元测试用例。Ø  运行:Alt+Shift+F10运行程序,Shift+F9启动调试,Ctrl+F2停止。Ø  调试:F7/F8/F9分别对应Step into,Step over,Continue。此外还有些我自定义的,例如水平分屏Ctrl+|等,和一些神奇的小功能Ctrl+Shift+V粘贴很早以前拷贝过的,Alt+Shift+Insert进入到列模式进行按列选中。7 最终榜单这榜单阵容太豪华了,后几名都是如此有用,毫不示弱。Ø  Top #10切来切去:Ctrl+TabØ  Top #9选你所想:Ctrl+WØ  Top #8代码生成:Template/Postfix +TabØ  Top #7发号施令:Ctrl+Shift+AØ  Top #6无处藏身:Shift+ShiftØ  Top #5自动完成:Ctrl+Shift+EnterØ  Top #4创造万物:Alt+Insert太难割舍,前三名并列吧!Ø  Top #1智能补全:Ctrl+Shift+SpaceØ  Top #1自我修复:Alt+EnterØ  Top #1重构一切:Ctrl+Shift+Alt+T
阅读全文
0 0
原创粉丝点击