下面以登录为例子,展示从前台到后端的一整套流程并进行分析.

首先介绍一下我的SSH的分层结构

  • action和service一起是业务逻辑层          action层调用service层
  • dao层是数据访问层,也叫做持久层          里面是对数据库的操作
  • model是数据库表对应的实体类              我把每个对应的hibernate的配置也写在了这里
  • conf包 这里放的是细分的spring和struts的配置文件  一般是一个业务模块一个配置文件
  • interceptor包  是我自己定义的拦截器     很多时候struts自带拦截器并不能达到我们的要求
  • common包     是自己定义的共用的方法   比如说 定义的常量  工具类

大体的分层就清晰了.

那么我们就上干货吧,直接上代码和分析. 这里只讲流程,不对调用的方法进行涉及.

1.首先是登录界面 logon.jsp

<s:form method="post" target="_parent" namespace="/login" action="loginAction" onsubmit="return checkInfor()">
<div class="login_left">
<h3 class="login_h3">欢迎登录图友网</h3>
<div class="login_sr">
用户名: <!-- <input type="text" class="login_inputYhm"> -->
<s:textfield cssClass="login_inputYhm" id="loginName" name="loginName" onfocus="selectText(this)" />
</div>
<div class="login_sr">
密码: &nbsp;&nbsp;&nbsp;<!-- <input type="password" class="login_inputMm"> -->
<s:password showPassword="true" cssClass="login_inputMm" id="password" name="password" onfocus="selectText(this)" />
</div>
<div class="login_sr">
<div style="float:left">验证码:</div>
&nbsp;&nbsp; <!-- <input type="text" name="validateCode" maxlength="4" class="login_inputYzm" style="float:left;"> -->
<s:textfield maxLength="4" cssClass="login_inputYzm" style="float:left;" name="validateCode" id="validateCode" value="验证码" onfocus="selectText(this)" />
<div class="login_inputYzmPic" style="float:left">
<img src="<%=basePath%>login/loginAction!findValidateCode" id="validateImage" onclick="refresh()" title="看不清,换一张">
</div>
<%-- <span class="login_inputYzmH" onclick="changeCode()">换一张</span> --%>
</div>
<div> <!-- <button type="submit" value="登录" style="height:30px;width:50px">登录</button> -->
<s:submit type="button" cssStyle="height:30px;width:50px" method="login" value="登录"></s:submit>
</div>
<div class="login_zcymm">
<a href="<%=basePath%>picturefriend/login/register.jsp">注册帐号</a>
</div>
</div>

点击提交的时候,web.xml中我们配置的struts拦截器会对请求进行拦截,去对应的struts配置文件寻找对应的action处理类,这里可以看到命名空间是/login action是loginAction

method是login.然后会去寻找/login对应的包  这个寻找顺序请自己看我之前的文章

2.struts-login.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts2.1.dtd">
<struts>
<package name="login" namespace="/login" extends="common">
<!-- 这里的common包是在strtus.xml中配置的 就是我们之前自定义的拦截器-->
<action name="loginAction" class="loginAction">
<!-- stream 直接向响应中发送原始数据 通常在用户下载时使用 contentType指定流的类型
contentLength以byte 计算流的长度,
contentDisposition指定文件的位置,通常为 filename=”文件的位置”,
-->
<result name="getValidateCode" type="stream">
<param name="inputName">imageInputStream</param>
<param name="contentType">image/jpeg</param>
</result>
<!-- <result name="result1" type="dispatcher">/picturefriend/main/userIndex.jsp</result>
<result name="result2" type="dispatcher">/picturefriend/main/userIndex.jsp</result> --> <result name="userSuccess" type="dispatcher">/picturefriend/main/userIndex.jsp</result>
<result name="adminSuccess" type="dispatcher">/picturefriend/main/adminIndex.jsp</result>
<result name="input" type="dispatcher">/picturefriend/login/login.jsp</result>
<result name="logout" type="redirect">/picturefriend/login/login.jsp</result> </action>
</package>
</struts>

找到了 /login包 然后寻找此包下名为loginAction的action.看到没每一个actionn都有几个result,result是根据业务逻辑返回的字符串去寻找对应的视图

可是为什么这里的class不是一个长长的全名路径是一个字符串呢?  这是因为我们在struts.xml配置了将bean交给了spring去处理,所以我们要根据这个loginAction去Spring找了.

3.applicationContext-action.xml

    <bean id="loginAction" class="com.chinasoft.action.login.LoginAction"
scope="prototype">
<property name="loginService" ref="loginService"></property>
<property name="productSortService" ref="productSortService"></property>
</bean>

这里的id就是我们的loginAction class是业务逻辑处理类, property是action处理类的属性,也就是说此action将会用到这两个service类.ref是bean的id.

4.com.chinasoft.action.login.LoginAction.java

因为我们的jsp上对应的方法是login 所以我们只需在业务逻辑类中关注login方法即可.

private LoginService loginService; 
public String login() { if (!getSession().get(Constant.SESSION_VALIDATE).toString()
.equalsIgnoreCase(validateCode)) {
getRequest().put("state", "2");
return INPUT;
}
//根据输入用户,查询User表
SysUser user = loginService.findUserByLoginName(loginName);
if (user != null) {// 根据用户名可以检索到用户信息
System.out.println("用户表中有该用户!");
return judgeUser(user);
} else {// 用户表中没有输入的帐号
return judgeAdmin();
} }

此处我们看到会调用loginService,循环上面的步骤
5.ApplicationContext-service.xml

<bean id="loginService" class="com.chinasoft.service.login.LoginServiceImpl"
scope="singleton">
<property name="userDao" ref="userDao"></property>
<property name="loginDao" ref="loginDao"></property>
</bean>

6.com.chinasoft.service.login.LoginServiceImpl
此处注意的是servie层开始面向接口编程,一个接口,一个实现类.我们调用的都是实现类

public SysUser findUserByLoginName(String pLoginName) {
try {
System.out.println("1111111");
return userDao.findUserByLoginName(pLoginName);
} catch (DataAccessException e) {
e.printStackTrace();
throw new BusinessException("出现系统错误,请与管理员联系",e);
}
}

7.ApplicationContext-dao.xml

<bean id="userDao" class="com.chinasoft.dao.user.UserDaoImpl"
scope="singleton">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>

8.com.chinasoft.dao.user.UserDaoImpl.java

public SysUser findUserByLoginName(String ploginName) {
String hql = "from SysUser where loginName = ?";
List<SysUser> users = getHibernateTemplate().find(hql, ploginName);
if (users.isEmpty()) {
return null;
} else {
System.out.println("user根据用户名查询普通用户信息成功!");
return users.get(0);
}
}

这里就到了查表了,但是我们实体类是怎么和表对应的啊?  我们用的是hibernate,这个ORM很强大,真的很强大. 我这么配置的
9.SysUser.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
          <!-- class的name是实体类 table是表名  dynamic-insert,dynamic-update是说和表进行比较 只改变被改变的值,未变动的值不做处理-->
 <class name="com.chinasoft.model.user.SysUser" table="SYS_USER" dynamic-insert="true" dynamic-update="true">
   <!-- id是主键  name是对应的实体类的属性  column对应表中的字段   generator是设置主键增长方式-->
  <id name="userId" column="USER_ID">
   <generator class="sequence">
    <param name="sequence">SEQ_SYS_USER</param>
   </generator>
  </id>
   <!-- property是其他属性与表对应的固定方式   name属性 column表的字段 type  表中字段类型-->
  <property name="birthday" column="BIRTHDAY" type="date"></property>
  <property name="email" column="EMAIL" type="string"></property>
  <property name="imageUrl" column="IMAGE_URL" type="string"></property>
  <property name="loginName" column="LOGIN_NAME" type="string"></property>
  <property name="isMale" column="IS_MALE" type="true_false"></property>
  <property name="password" column="PASSWORD" type="string"></property>
  <property name="registerTime" column="REGISTER_TIME" type="timestamp"></property>
  <property name="userName" column="USER_NAME" type="string"></property>
  <property name="isLock" column="IS_LOCK" type="yes_no"></property>
  <property name="phoneNum" column="PHONE_NUM" type="string"></property>
   <!-- 多对一  永远是在多的一方进行配置-->
  <!-- 与职位关联配置 -->
  <many-to-one name="sysJob" class="com.chinasoft.model.job.SysJob" column="JOB_ID">
  </many-to-one>
  <!-- 与登录关联配置 -->
  <set name="sysLogin" table="SYS_LOGIN" inverse="true" fetch="select">
   <key>
    <column name="USER_ID"></column>
   </key>
   <one-to-many class="com.chinasoft.model.login.SysLogin"/>
  </set>
  
   <!-- 与作品表关联-->
        <set name="products" table="PRODUCT" inverse="true" fetch="select">
            <key>
                <column name="CREATE_USER" >
                </column>
            </key>
            <one-to-many class="com.chinasoft.model.product.Product" />
        </set>
        <!-- 与作品查询表关联-->
        <set name="productQuerys" table="PRODUCT_QUERY" inverse="true" fetch="select">
            <key>
                <column name="USER_ID" >
                </column>
            </key>
            <one-to-many class="com.chinasoft.model.product.ProductQuery" />
        </set>
       
         <!-- 与作品评论表关联-->
        <set name="porductComments" table="PRODUCT_COMMENT" inverse="true" fetch="select">
            <key>
                <column name="USER_ID" >
                </column>
            </key>
            <one-to-many class="com.chinasoft.model.comment.ProductComment" />
        </set>
       
        <!-- 与作品评论回复表关联-->
        <set name="commentReplys" table="COMMENT_REPLY" inverse="true" fetch="select">
            <key>
                <column name="USER_ID" >
                </column>
            </key>
            <one-to-many class="com.chinasoft.model.reply.CommentReply" />
        </set>
  
 </class>
</hibernate-mapping>

然后根据查询结果,action层会返回一个字符串,再去struts-login.xml中寻找对应的结果视图就完成了.
前前后后两周多终于把SSH基本掌握了,恭喜自己!

如何写一个SSH项目(三)如何进行交互的的更多相关文章

  1. 如何写一个SSH项目(一)程序设计大体思路

    SSH:分别是指Spring,Struts,Hibernate. 后来Struts2代替了Struts,所以我们常说的SSH是指Spring,Struts2,Hibenate. 其中Spring一般用 ...

  2. 无监控不运维——使用 Python 写一个小小的项目监控

    在公司里做的一个接口系统,主要是对接第三方的系统接口,所以,这个系统里会和很多其他公司的项目交互.随之而来一个很蛋疼的问题,这么多公司的接口,不同公司接口的稳定性差别很大,访问量大的时候,有的不怎么行 ...

  3. php 如何写一个自己项目的安装程序

    版权声明:此篇文章只是用作笔记,如果版权冲突,请邮件通知一下(15201155501@163.com) https://blog.csdn.net/shenpengchao/article/detai ...

  4. windows环境30分钟从0开始快速搭建第一个docker项目(带数据库交互)

    前言 小白直接上手 docker  构建我们的第一个项目,简单粗暴,后续各种概念边写边了解,各种概念性的内容就不展开,没了解过的点击 Docker 教程 进行初步了解. Docker 是一个开源的应用 ...

  5. 也谈如何写一个Webserver(三)

    在上一篇里,我介绍了如何应用socket和epoll来组织和管理从客户端(如,浏览器)传入的连接,通过设置非阻塞连接让Webserver有更好的性能. 下面,我介绍一下在我写的Webserver Ma ...

  6. 【原创】纯OO:从设计到编码写一个FlappyBird (三)

    第二部分请点这里 下面首先来实现Bing接口! 实现Bing接口的类取名SimpleBing. 容易发现,SimpleBing类总的来说要向下,但点击一下又得向上,向上到了一定界限又得向下,但我们又只 ...

  7. 搭建一个SSH项目框架的步骤

    1.导入jar包(38个) 2.配置文件 applicationContext,xml (beans.xml) (数据源.LocalSessionFactoryBean.事务管理器.事务通知.AOP切 ...

  8. python写一个能生成三种一句话木马的脚本

    代码: import time import os from threading import Thread import optparse def aspyijuhua(): try: juy=op ...

  9. 写一个js向左滑动删除 交互特效的插件——Html5 touchmove

    需求描述 需要实现类似QQ中对联系人的操作:向左滑动,滑出删除按钮.滑动超过一半时松开则自动滑到底,不到一半时松开则返回原处. 纯js实现 使用了h5的touchmove等事件,以及用js动态改变cs ...

随机推荐

  1. 虚拟机Ubuntu无法上网问题解决过程

    查看了网上大部分经验贴,都没有解决问题,只好自己思考琢磨,以下是思考解决过程 1.查看文件配置 2.查看虚拟机网络配置方式 3.查看硬件驱动是否存在 4.配置完文件ifcfg-eth0后重启,无效(虚 ...

  2. Serializable 都这么牛逼了,Parcelable 还要你何用?

    一些闲聊 距离上一篇文章似乎又是很久了,看起来也没有很多反馈,催更就更不用说了.哈哈,放弃了. 话说最近公司在招聘一批至少 5 年开发经验的 Android 开发工程师,我也是忙开了花,激动得不行呀. ...

  3. 简单了解enum

    enum的性质: 1.枚举类型的实例都是常量 2.要使用enum,需要创建一个该类型的引用,并将其赋值给某个实例 3.常用的方法:  *     toString():某个enum实例的名字  *   ...

  4. POJ A Simple Problem with Integers 线段树 lazy-target 区间跟新

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 105742 ...

  5. CCF-201409-1-相邻数对

    问题描述 试题编号: 201409-1 试题名称: 相邻数对 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1. ...

  6. MySQL 性能优化的最佳20多条经验分享(一)(转)

    当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这 ...

  7. centos7 忘记mysql root密码办法

    1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的状态下,其他的用户也可以任意地登录和 ...

  8. oralce11g导出dmp然后导入Oracle10g

    一次Oracle11g数据库导入 Oracle10g数据库操作笔记 11g备份导入10g的时候会抛错直接阻止导入. 但是有时候还必须得把11g的数据库导入到10g我今天就遇到了这种情况. 一开始 ...

  9. 跟着鬼哥学so改动,二,进行篇

    图/文  听鬼哥说故事 继续上文的内容---------------------------------- 0x1:測试文件的编写 经过上一篇文章的基础学习,如今我们開始进行是用的部分. 既然我们能够 ...

  10. 掌上快递 APP 项目之概述篇

    概述 学习Android开发也有一段时间了,利用业余时间独立制作的一款快递类APP软件.大概2个多星期吧,自己将其定位为"集快递信息追踪.附近快递点查询. 快递公司投诉功能为一体的便民生活类 ...