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

总结:

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();//addStudentForm
String path = mapping.getPath();
String type = mapping.getType();
String[] forwards = mapping.findForwards();
for(String fname: forwards){
    System.out.println(fname);
}
System.out.println(name);// addStudentForm
System.out.println(path);// //addStudentAction
System.out.println(type);// com.mamh.struts1.demo.action.AddStudentAction
System.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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值