{"id":19446816,"url":"https://github.com/jonashao/ssh","last_synced_at":"2025-10-15T19:56:25.081Z","repository":{"id":85676251,"uuid":"58607694","full_name":"jonashao/ssh","owner":"jonashao","description":"An example of Spring  + Struts2 + Hibernate, built with gradle, work on Intellij.","archived":false,"fork":false,"pushed_at":"2016-08-05T01:08:21.000Z","size":875,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-10T18:31:49.364Z","etag":null,"topics":["gradle","hibernate","intellij","spring","struts2"],"latest_commit_sha":null,"homepage":"http://junnanhao.com/2016/08/08/ssh/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonashao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-05-12T04:31:20.000Z","updated_at":"2020-03-17T03:44:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"febd91d5-4089-427e-8d32-b13bfe6cd60d","html_url":"https://github.com/jonashao/ssh","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jonashao/ssh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashao%2Fssh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashao%2Fssh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashao%2Fssh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashao%2Fssh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonashao","download_url":"https://codeload.github.com/jonashao/ssh/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashao%2Fssh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279110097,"owners_count":26105905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","hibernate","intellij","spring","struts2"],"created_at":"2024-11-10T16:15:16.798Z","updated_at":"2025-10-15T19:56:25.073Z","avatar_url":"https://github.com/jonashao.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intellij 用gradle搭建Spring+Hibernate+Struts2\n\n项目源码例子:\nhttps://github.com/JonasHao/SSH-User-Signup\n\n准备：\nIntellij + JDK 8 + Tomcat 9\n\n# 新建项目\nFile -\u003e New -\u003e Project\n\n左侧选择Gradle,\nProject SDK配置成JDK的目录。\nAdditional Libraries and Frameworks中勾选Java和Web，点击Next\n![](img/1-New-Project.png)\n\n进入gradle配置页面，groupID填写组织域名。\nArtifectId填写项目的名称。点击Next-Next\n![](img/2-New-Project-Gradle.png)\n\n勾选`Create directories for empty content roots automatically`，\n以便自动创建/java, /resources 等目录，也可手动创建。\n![](img/3-New-Project-2.png)\n\n选择项目目录，然后Finish。\n\n# 配置Gradle文件\n第一次打开项目，可能会需要一段时间更新gradle版本，请耐心等候完成。\n![](img/4-Refresh-Gradle.png)\n\n更新gradle完成之后，修改 `build.gradle`，\n这是我的，包含了spring、java ee、 struts2 、 hibernate、 jdbc的依赖：\n\n```gradle\ngroup 'com.junnanhao'\nversion '1.0-SNAPSHOT'\n\napply plugin: 'java'\napply plugin: 'spring-boot'\n\nsourceCompatibility = 1.8\ntargetCompatibility = 1.8\n\n\nrepositories {\n    mavenCentral()\n}\n\n\nbuildscript {\n    ext {\n        springBootVersion = '1.3.3.RELEASE'\n    }\n    repositories {\n        mavenCentral()\n    }\n    dependencies {\n        classpath(\"org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}\")\n    }\n}\n\n\ndependencies {\n    // 将libs 文件夹中的jar 全部打包进工程\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n\n    testCompile group: 'junit', name: 'junit', version: '4.11'\n\n    // spring\n    testCompile('org.springframework.boot:spring-boot-starter-test')\n    compile(\"org.springframework.boot:spring-boot-starter-web\")\n    compile('org.springframework.boot:spring-boot-starter')\n    compile('org.springframework:spring-orm')\n\n    // compile java ee 7\n    compile('javax:javaee-api:7.0')\n\n    // struts\n    compile('org.apache.struts:struts2-core:2.3.28')\n    compile('org.apache.struts:struts2-spring-plugin:2.3.28')\n    compile('org.apache.struts:struts2-convention-plugin:2.3.28')\n\n    // hibernate\n    compile ('org.hibernate:hibernate-core:5.1.0.Final')\n\n    // jdbc\n    compile('mysql:mysql-connector-java:5.1.6')\n\n}\n\n```\nRefresh gradle, Intellij会自动检测到gradle内容的变动，并询问是否要refresh,\n如果没有检测到，点击窗口右侧的gradle, 一个回收的标志就是 Refresh，如图：\n\n![](img/5-Button-Refresh-Gradle.png)\n\n此时，Intllij自动从maven下载缺失的依赖项。\n这将是漫长的过程，因为要下载Spring、Struts2、Hibernate以及 Java ee的库文件 (如果之前没有下载过的话）。\n\n# 配置项目\n至此，我们已经为项目做好了充分准备，所有sdk都已就绪，现在开始配置项目的框架。\n\n## 添加SSH框架\n在demo/src/main上点击鼠标右键，点击Add Framework Support:\n![](img/6-Add-Framework-Support.png)\n\n在左侧依次选择Struts2、 Spring MVC 和 Hibernate：\n![](img/7-Add-Struts2.png)\n![](img/7-Add-Spring-Hibernate.png)\n\n此时Intellij会检测到新的框架，并提醒配置。\n我们不需要修改默认配置，不过可以点进去看一看。\n如果没有提醒也没关系，在File -\u003e Project Settings（快捷键：`Ctrl+Alt+Shift+S`)\n![](img/8-config-struts2.png)\n\n现在的目录是这样子的：\n\n![](img/9-files.png)\n\n默认的配置都已经是OK的了, 唯一要做的是将Hibernate集成到Spring中。\n\n首先配置`hibernate.cfg.xml`:\n根据你的电脑的情况设置以下项:\n- connection.url\n- connection.driver_class\n- connection.username\n- connection.password\n- dialect\n- current_session_context_class\n\n下面是我的配置,可供参考。\n```xml\n\u003c?xml version='1.0' encoding='utf-8'?\u003e\n\u003c!DOCTYPE hibernate-configuration PUBLIC\n        \"-//Hibernate/Hibernate Configuration DTD//EN\"\n        \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\"\u003e\n\n\u003chibernate-configuration\u003e\n    \u003csession-factory\u003e\n        \u003c!-- Database connection settings --\u003e\n        \u003cproperty name=\"connection.driver_class\"\u003ecom.mysql.jdbc.Driver\u003c/property\u003e\n        \u003cproperty name=\"connection.url\"\u003ejdbc:mysql://localhost:3306/demo\u003c/property\u003e\n        \u003cproperty name=\"connection.username\"\u003e******\u003c/property\u003e\n        \u003cproperty name=\"connection.password\"\u003e******\u003c/property\u003e\n\n        \u003c!-- JDBC connection pool (use the built-in) --\u003e\n        \u003cproperty name=\"connection.pool_size\"\u003e10\u003c/property\u003e\n\n        \u003c!-- SQL dialect --\u003e\n        \u003cproperty name=\"dialect\"\u003eorg.hibernate.dialect.MySQLDialect\u003c/property\u003e\n\n        \u003c!-- Enable Hibernate's automatic session context management --\u003e\n        \u003cproperty name=\"current_session_context_class\"\u003ethread\u003c/property\u003e\n\n        \u003c!-- Echo all executed SQL to stdout --\u003e\n        \u003cproperty name=\"show_sql\"\u003etrue\u003c/property\u003e\n        \u003cproperty name=\"format_sql\"\u003etrue\u003c/property\u003e\n\n        \u003c!-- Drop and re-create the database schema on startup --\u003e\n        \u003cproperty name=\"hbm2ddl.auto\"\u003eupdate\u003c/property\u003e\n\n    \u003c/session-factory\u003e\n\u003c/hibernate-configuration\u003e\n```\n在Spring的配置文件`applicationContext.xml`中加入sessionFactory这一bean.\n这样Spring会为所有依赖于id为sessionFactory的bean注入依赖 （通过调用那些类的`setSessionFactory() `方法。）\n```xml\n \u003cbean id=\"sessionFactory\" class=\"org.springframework.orm.hibernate5.LocalSessionFactoryBean\"\u003e\n        \u003cproperty name=\"configLocations\" value=\"classpath:hibernate.cfg.xml\"/\u003e\n \u003c/bean\u003e\n```\n\n重启一下项目，新打开时，Intellij会提醒检测到Hibernate的数据源，点击Discover and setup：\n![](img/15-hibernate-detect.png)\n\n\n## 配置Tomcat服务器\n1. Edit Configurations\n![](img/12-tomcat-1.png)\n\n2. Add new configuration - tomcat server - Local\n![](img/12-tomcat-2.png)\n\n3. Configure Application server， 选择Tomcat SDK Home目录\n![](img/12-tomcat-3.png)\n\n4. Deployment - 点击加号 - Artifact - 选择默认的Artifact\n![](img/12-tomcat-4.png)\n\n5. 点击铅笔的图标， 编辑Artifact（也可以在Project Settings的右侧找到Artifact)\n![](img/12-tomcat-5.png)\n\n6. 将demo_main模块添加到artifact, 做法是：右键在demo_main上，点击Put into Ouput Root。 demo是我的项目名字。\n![](img/12-tomcat-6.png)\n\n7. 添加xml文件到artifact，hibernate.cfg.xml和struts.xml（所有xml文件都）默认情况不会被自动添加到build结果中，需要手动配置：\n点击加号 - File, 选择两个xml文件\n![](img/12-tomcat-7.png)\n![](img/12-tomcat-8.png)\n\nOK!\n\n现在，整个配置都已经完成了。\n点击tomcat猫旁边的绿色三角形运行一下！\n![](img/14-run.png)\n\n看到这样的结果：\n\n![](img/14-run-2.png)\n\n就说明tomcat配置成功了，这是index.jsp的页面，默认的欢迎页。\n\n\n下面是一个用户注册的例子。\n\n# 用户注册的例子\n## 需求分析\n网页上有一个表单，用户可以填入ID、密码、重复输入的密码、手机号码和邮箱，其中只有邮箱是选填的。\n后台先校验数据，校验失败给用户相应的提醒，校验成功之后查询数据库，判断这个ID是否已经被注册，如果没有则创建一个用户，并永久保存到数据库中，否则提示用户这个ID已经被占用。\n\n## 自顶向下设计\n### 1. signUp.jsp\n注册信息的表单，提交之后指向`SignUpAction`\n\n### 2. UserAction.java\n因为除了注册，用户还需要登录，我们将登录注册的action都放在UserAction.java中，只需在`struts.xml`中为每个action指定各自的方法。\n\nSignUpAction指向UserAction中的`public String signUp()`方法。\n在`signUp()`中，先做表单校验：\n用户名的长度、包含字符，密码的长度、特殊字符，两次输入密码是否一致，手机号码格式以及邮箱格式。\n记录校验不通过的字段以及原因，为之后提醒用户。\n\n校验成功之后通过UserDao根据ID查询用户，查到用户不为空则表示ID被占用，查询为空则创建一个User对象，并通过UserDao保存User到数据库。\n\n### 3. UserDao.java\n暂时需要实现两个方法：\n`User findUserByID(String ID)`\n`void addUser(User user)`\n\n## 自底向上实现\n首先在demo/src/main/java 下创建几个包：\n- /action\n- /dao\n- /po\n- /service\n\n### User.java\n在/po下创建一个POJO（Pure Old Java Object)类：User.java.\n```java\npublic class User {\n    private String ID;\n    private String phone;\n    private String email;\n    private long password;\n}\n```\n然后充分利用Intellij的便捷。鼠标在password;后点一下，让焦点在User类内。\n按快捷键`Alt + Insert`,或者鼠标右键-Generate...\n\n![](img/10-generate-getter-and-setter.png)\n\n点Getter and Setter，然后全选，点击OK。\n\n再用`Alt + Insert`，点Constructor，分别创建一个没有参数的构造函数和一个传入ID、密码、手机号的构造函数（邮箱在这里是选填的）。\n\n接下来将User类标记为Hibernate的实体（@Entity),\n\n并在getID()上标记ID为实体User的主键（@Id)\n\n最后，User.java是这样：\n```java\npackage po;\n\nimport javax.persistence.Entity;\nimport javax.persistence.Id;\n\n@Entity\npublic class User {\n    private String ID;\n    private String phone;\n    private String email;\n    private long password;\n\n    public User(String ID, String phone, long password) {\n        this.ID = ID;\n        this.phone = phone;\n        this.password = password;\n    }\n\n    public User() {\n    }\n\n    @Id\n    public String getID() {\n        return ID;\n    }\n\n    public void setID(String ID) {\n        this.ID = ID;\n    }\n\n    public String getPhone() {\n        return phone;\n    }\n\n    public void setPhone(String phone) {\n        this.phone = phone;\n    }\n\n    public String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n\n    public long getPassword() {\n        return password;\n    }\n\n    public void setPassword(long password) {\n        this.password = password;\n    }\n}\n```\n\n更多标记请参考[Hibernate官方文档](http://docs.jboss.org/hibernate/orm/5.1/quickstart/html_single/#tutorial_annotations)\n\n写完User.java之后，把它配置到`Hibernate.cfg.xml`中。\n```xml\n \u003csession-factory\u003e\n        ...\n        \u003cmapping class=\"po.User\"/\u003e\n \u003c/session-factory\u003e\n```\n\n### UserDao.java\n用Hibernate的sessionFactory创建一次会话，创建方式有两种\n1. `sessionFactory.openSession();`\n2. `sessionFactory.getCurrentSession()`\n\n第一种创建了一个新的会话，需要手动flush、commit transaction、 close session.\n适合于每次请求一次会话的情况。\n\n第二种获取当前线程的会话，不需要手动关闭，会被自动处理。\n适合于长会话。\n\n这里用到了Hibernate Query Language， 跟Sql十分相像，但注意From子句后跟的不是表名，而是对应实体类的名字。\n更多有关HQL请参考[Hibernate - Query Language](http://www.tutorialspoint.com/hibernate/hibernate_query_language.htm)。\n```java\npackage dao;\n\nimport org.hibernate.Session;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.Transaction;\nimport po.User;\n\nimport java.util.List;\n\n\npublic class UserDao{\n\n    private SessionFactory sessionFactory;\n    \n    public String addUser(User user) {\n        Session session = sessionFactory.openSession();\n        Transaction transaction = session.beginTransaction();\n        session.save(user);\n        transaction.commit();\n        session.flush();\n        session.close();\n        return \"ok\";\n    }\n\n    public User findUserByID(String ID) {\n        sessionFactory.getCurrentSession().beginTransaction();\n\n        List list = sessionFactory.getCurrentSession().\n                createQuery(\"from User where ID = ?\").\n                setParameter(0, ID).list();\n\n        if (list.size()\u003e0) {\n            Object object = list.get(0);\n            System.out.println(object);\n            return (User) object;\n        }\n\n        return null;\n    }\n    \n\n    public void setSessionFactory(SessionFactory sessionFactory) {\n        this.sessionFactory = sessionFactory;\n    }\n}\n\n```\n查询数据用到`sessionFactory`，它是从哪里获取的呢？\n\nSpring在这里发挥作用了，它帮助我们注入这些依赖，只需要告诉Spring：UserDao要用到sessionFactory，那么Spring会在初始化的时候，为所有用到sessionFactory的类通过`setSessionFactory()`注入sessionFactory的一个实例。\n\n做法也很简单，用Intellij的Generate（`ALT + Insert`)-Spring Setter Dependency\n![](img/11-spring-dependency.png)\n\n选择sessionFactory.（没错，这就是我们在整合Hibernate进Spring的时候创建的bean)\n![](img/11-spring-dependency-sessionFactory.png)\n\n以上Generate的过程，相当于Intellij帮我们在`applicationContext.xml`中加入了一个bean：\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cbeans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\"\u003e\n\n    \u003c!--将Hibernate整合进Spring--\u003e\n    \u003cbean id=\"sessionFactory\" class=\"org.springframework.orm.hibernate5.LocalSessionFactoryBean\"\u003e\n        \u003cproperty name=\"configLocations\" value=\"classpath:hibernate.cfg.xml\"/\u003e\n    \u003c/bean\u003e\n    \n    \u003c!--以下是Generate自动生成的代码--\u003e\n    \u003cbean class=\"dao.UserDao\" id=\"userDao\"\u003e\n        \u003cproperty name=\"sessionFactory\" ref=\"sessionFactory\"/\u003e\n    \u003c/bean\u003e\n    \n\u003c/beans\u003e\n```\n\n### UserAction.java\n代码的主要结构：\n```java\npackage action;\n\nimport dao.UserDao;\nimport org.apache.struts2.dispatcher.DefaultActionSupport;\n\n\npublic class UserAction extends DefaultActionSupport {\n\n    \n    private String username;\n    private String password;\n    private String passwordAgain;\n    private String phone;\n    private String email;\n\n    private UserDao userDao;\n\n    UserAction() {\n    }\n\n  \n    public String singUp() throws Exception {\n        return INPUT;\n    }\n\n\n    /**\n     * 校验用户名\n     */\n    private boolean validateUsername() {\n        return false;\n    }\n\n    /**\n     * 校验密码，只能包含数字、字母、下划线、符号，长度为6-20位\n     */\n    private boolean validatePassword() {\n        return false;\n    }\n    \n}\n```\n\n然后用Generate(`Alt + Insert`)生成Getter 和 Setter, 以及userDao的Spring Setter Dependency.\n\ngetter和setter函数使Action与jsp直接交互数据，也就是说，jsp表单里的表单项与一个私有成员（ID,password,phone,email)绑定之后，会自动调用setter方法。\n\nSpring Setter 为我们注入UserDao。\n\n这是一份完整的UserAction.java代码\n```java\npackage action;\n\nimport dao.UserDao;\nimport org.apache.struts2.dispatcher.DefaultActionSupport;\nimport po.User;\n\n\npublic class UserAction extends DefaultActionSupport {\n\n    \n    private String username;\n    private String password;\n    private String passwordAgain;\n    private String phone;\n    private String email;\n\n    private UserDao userDao;\n\n    UserAction() {\n    }\n\n  \n    public String singUp() throws Exception {\n        if (validateUsername() \u0026\u0026 validatePassword()) {\n\n            if (!password.equals(passwordAgain)) {\n                addFieldError(\"passwordAgain\", \"两次密码输入不一致\");\n            }\n\n            User user = userDao.findUserByID(username);\n            if (user != null) {\n                addFieldError(\"username\", \"用户名已经被占用\");\n                return INPUT;\n            }\n\n            user = new User(phone,username, password.hashCode());\n\n            userDao.addUser(user);\n            return SUCCESS;\n\n        }\n        return INPUT;\n    }\n\n\n    /**\n     * 校验用户名\n     */\n    private boolean validateUsername() {\n        if (username != null \u0026\u0026 username.matches(\"^[a-z0-9_-]{3,15}$\")) {\n            return true;\n        }\n        addFieldError(\"username\", \"用户名不符合规范\");\n        return false;\n    }\n\n    /**\n     * 校验密码，只能包含数字、字母、下划线、符号，长度为6-20位\n     */\n    private boolean validatePassword() {\n        if (!password.isEmpty() \u0026\u0026 password.matches(\"[0-9a-zA-Z!@#$%^?,./]{6,20}\")) {\n            return true;\n        }\n        addFieldError(\"password\", \"密码不符合规范\");\n        return false;\n    }\n\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getPasswordAgain() {\n        return passwordAgain;\n    }\n\n    public void setPasswordAgain(String passwordAgain) {\n        this.passwordAgain = passwordAgain;\n    }\n\n    public String getPhone() {\n        return phone;\n    }\n\n    public void setPhone(String phone) {\n        this.phone = phone;\n    }\n\n    public String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n\n    public void setUserDao(UserDao userDao) {\n        this.userDao = userDao;\n    }\n}\n\n```\n\u003e`addFieldError(feildName, errorMessage)`\n\u003e 记录的错误信息，将会在返回结果为INPUT之后，呈现在jsp中，效果如图：\n\n\u003e ![](img/13-validate-2.png)\n\n### struts.xml\n接下来，我们在struts.xml中注册UserAction:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\n\u003c!DOCTYPE struts PUBLIC\n        \"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN\"\n        \"http://struts.apache.org/dtds/struts-2.3.dtd\"\u003e\n\u003cstruts\u003e\n    \u003cpackage name=\"default\" namespace=\"/\" extends=\"struts-default\"\u003e\n        \n        \u003caction name=\"signUp\" class=\"action.UserAction\" method=\"singUp\"\u003e\n            \u003cresult name=\"input\"\u003eindex.jsp\u003c/result\u003e\n            \u003cresult name=\"success\"\u003ewelcome.jsp \u003c/result\u003e\n        \u003c/action\u003e\n        \n    \u003c/package\u003e\n\u003c/struts\u003e\n```\n\n### index.jsp\n最后在jsp中添加一个表单，（index.jsp是默认的欢迎页。）\n\n不要忘了在头部引入struts的标签库，\n\n``` html\n\u003c%@ taglib prefix=\"s\" uri=\"/struts-tags\" %\u003e\n\n \u003cs:form action=\"signUp\" validate=\"true\" \u003e\n    \u003cs:textfield name=\"username\" label=\"用户名\" maxLength=\"20\" required=\"true\"/\u003e\n    \u003cs:password name=\"password\" label=\"密码\" maxLength=\"16\" required=\"true\"/\u003e\n    \u003cs:password name=\"passwordAgain\" label=\"确认密码\" maxLength=\"16\" required=\"true\"/\u003e\n    \u003cs:textfield name=\"phone\" label=\"电话\" maxLength=\"15\" required=\"true\"/\u003e\n    \u003cs:textfield name=\"email\" label=\"电子邮箱\"/\u003e\n\n    \u003cs:submit value=\"注册\"/\u003e\n  \u003c/s:form\u003e  \n  \n  ```\n`name`属性绑定action的一个私有成员，提交表单之后将自动调用对应setter函数。\n\n### welcome.jsp\n新建一个jsp页面，注册成功后将跳转到这个页面。\n\n最后，运行Tomcat：\n\n![](img/16-demo.png)\n\n填写表单之后：\n![](img/16-demo-2.png)\n\n刷新一下数据库，可以看到新的记录已经插入：\n![](img/16-demo-3.png)\n\n至此，简单的用户注册的例子已经完成，欢迎大家指正提建议。\n\n项目源码例子:\nhttps://github.com/JonasHao/SSH-User-Signup","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashao%2Fssh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonashao%2Fssh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashao%2Fssh/lists"}