JAVAweb之SSH框架

SSH框架( struts+spring+hibernate)

开发环境 myeclipes2015 sqlserver2012 Java

简述

SSH是 struts+spring+hibernate的一个集成框架,是06年之前较为流行的一种Web应用程序开源框架.。集成SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理struts和hibernate。
struts请求路径
JAVAweb之SSH框架_第1张图片
SSH框架优点
优秀的解耦性,很少有软件产品的需求从一开始就完全是固定的。客户对软件需求,是随着软件开发过程的深入,不断明晰起来的。因此,常常遇到软件开发到一定程度时,由于客户对软件需求发生了变化,使得软件的实现不得不随之改变。ssh三层构架,控制层依赖于业务逻辑层,但绝不与任何具体的业务逻辑组件耦合,只与接口耦合;同样,业务逻辑层依赖于DAO层,也不会与任何具体的DAO组件耦合,而是面向接口编程。采用这种方式的软件实现,即使软件的部分发生改变,其他部分也不会改变。

框架解析

Struts

(一般开发选用的是Struts2【Struts的升级版】})
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。

spring

Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。Spring,使用基本的实体JavaBean来完成以前只能用EJB完成的事情。而其核心则是控制反转(IOC)和面向切面编程(AOP)。使用Spring,意味着一个对象的创建再也不是自己new出来的,而是全权交给了IOC容器去实例化。与此同时,Spring通过采用依赖注入(DI)的方式,通过属性的Setter和Getter方法来注入这个对象的属性,这样的好处就是不完全依赖于容器的API,且查询依赖与代码实现了解耦。而AOP,则是将应用的业务逻辑和系统级服务(例如事务)分离开来,进行内聚性的开发,应用对象只负责完成业务逻辑而不关心日志或者事务的处理。
spring优势
spring提高了一种对象管理方法,有效的组织系统中间层对象。是框架的完美“粘合剂”。有利于面向接口编程习惯的养成,使代码结构清晰。

hibernate

Hibernate,是负责了跟数据库的交接。通过持久化数据对象,进行对象关系的映射,并以对象的角度来访问数据库。通过封装JDBC,使得开发人员可以以面向对象编程的思想来操控数据库,从而摆脱了以往使用JDBC编程时的“死板”操作。通过hibernate.cfg.xml文件来取代以往的JDBC连接数据库的一大串代码,通过XXX(实体Bean的类名).hbm.xml文件来与数据库的具体表进行映射。并且Hibernate有自己的HQL语句,与数据库的SQL语句相似,但不同的是HQL语句在面向对象编程的角度上,通过Session的createQuery方法创建户一个query对象,由这个对象来完成对数据库的增删改查等操作。通过Struts2中Action的返回值,来调用Dao层中的业务处理。
hibernate优势
hibernate是JDBC轻量级的封装,占用内存较少,性能比较高。与JDBC相比,如果开发JDBC的人员技术能力非常强,hibernate执行效率会比JDBC弱一些,但是大部分情况是程序员在使用JDBC时是不可能做到最高效率,hibernate可以帮大部分开发人员提高运行效率。可以引入第三方二级缓存,提高系统查询效率,减少系统里存在大量单例类(singleton),大量的单例类,会降低系统的可测试性和面向对象程度。Hibernate兼容JDBC。理论上可以应用在任何使用JDBC的场景。
可以逆向工程,简化了手写model实体类的繁琐。

整体设计

表示层 (jsp页面)用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。login.jsp等layUI前端框架。
业务逻辑层 (Iplm,DAO,接口及接口实现,action,Servlet包)业务规则的制定、业务流程的实现等与业务需求有关的系统设计,对于数据访问层而言,它是调用者;对于表示层而言,它却是被调用者。UserDAO.java/ UserDAOImpl.java,AddcardAction.java/ FileUploadServlet.java
模块层 (hibernate逆向工程)实体层model包),以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。TUser.java/TUser.hbm.xml
数据持久层 (SQL server,基类实现,hql)主要是负责数据库的访问,可以访问数据库系统、二进制文件、文本文档或是XML文档。iHibBaseDAOImpl.java/ iHibBaseDAO.java

DAO接口模式为了减少业务逻辑和数据访问逻辑之间的耦合,当一个持久层框架被应用时,该模式将会减少业务对象和该框架之间的耦合,这样我们可以不修改业务对象而选择不同的持久层框架的实现。
业务逻辑层:包含了系统所需要的所有功能上的算法和计算过程,并与数据访问层和表现层交互。服务端返回数据的处理以及相应页面的改变。

设计原则:
业务层接口的设计原则:一个实体类一个接口,一次提交一个业务方法。业务方法的参数来自表现层。
持久层接口的设计原则:一个实体类一个接口,一次数据库操作一个持久方法。

实例手把手教学搭建

开发工具:myeclipes2015 sqlserver2012

  1. 新建一个SSHtest的web project项目
    JAVAweb之SSH框架_第2张图片
    JAVAweb之SSH框架_第3张图片
    输入项目名称,根据需要选择各项版本(一般默认即可),点击下一步
    JAVAweb之SSH框架_第4张图片
    点击下一步
    JAVAweb之SSH框架_第5张图片
    勾选后点击下一步
    JAVAweb之SSH框架_第6张图片
    点击Finish,项目就建好了。

  2. 搭建框架

●创建hibernate
JAVAweb之SSH框架_第7张图片
JAVAweb之SSH框架_第8张图片
为了更好的与spring匹配我们这里选择3.3版本的hibernate,选好后点击下一步
JAVAweb之SSH框架_第9张图片
根据上图操作就建立好了hibernate的session工厂。
接下来我们看一下建好的hibernate配置文件
JAVAweb之SSH框架_第10张图片在hibernate配置文件里配置与数据库的连接,获得数据持久化(相关配置会在后面步骤中介绍)

●创建spring
Spring整合Hibernate(一般先建hibernate再建spring,因为后建spring的话,就会自动把一些相关配置整合到spring里,减少了手动操作的麻烦)
JAVAweb之SSH框架_第11张图片
JAVAweb之SSH框架_第12张图片
spring一般选4.1版本,切合hibernate3.3,(记得选择版本的时候,两个版本要相对应,否则会因为缺失相应的架包而报错)点击下一步
JAVAweb之SSH框架_第13张图片
JAVAweb之SSH框架_第14张图片你不用管,直接下一步
JAVAweb之SSH框架_第15张图片
到此步,点击Finish,现在spring就创建好了
接下来我们来看创建好的spring配置文件
JAVAweb之SSH框架_第16张图片
●创建Struts2
JAVAweb之SSH框架_第17张图片
JAVAweb之SSH框架_第18张图片
选择2.1版本,点击下一步
JAVAweb之SSH框架_第19张图片
JAVAweb之SSH框架_第20张图片
到此步点击Finish,Struts2就创建好。
接下来我们来看Struts2的配置文件
JAVAweb之SSH框架_第21张图片
现在我们已经完成了基本SSH框架的搭建。
JAVAweb之SSH框架_第22张图片我们的框架布局基本就搭建完成了,我们先来运行测试一下(一般运行没错,就说明搭建没问题)
将项目部署到Tomcat上:
JAVAweb之SSH框架_第23张图片
运行
JAVAweb之SSH框架_第24张图片

因为要连接数据库,所以我们要新建一个数据库
●以sqlserver2012为例,新建一个名为SSHtest的数据库
JAVAweb之SSH框架_第25张图片
创建数据库
JAVAweb之SSH框架_第26张图片
点击确定,数据库就创好了。
我们在这了以用户登录为例,建一张用户表T_User
JAVAweb之SSH框架_第27张图片
填写数据
在这里插入图片描述
3. 创建所需包
JAVAweb之SSH框架_第28张图片4 . 配置框架
●hibernate连接数据库,获得持久化数据
新建数据池database
JAVAweb之SSH框架_第29张图片
JAVAweb之SSH框架_第30张图片
操作完以上点击下一步
JAVAweb之SSH框架_第31张图片
点击Finish,数据库连接池就做好了
在这里插入图片描述
hibernate配置
JAVAweb之SSH框架_第32张图片
操作完以上记得ctrl+s保存,这样hibernate就配置好了。
接下来我们看一下hibernate的配置文件
JAVAweb之SSH框架_第33张图片
hibernate逆向工程(获得model实体类)
JAVAweb之SSH框架_第34张图片
JAVAweb之SSH框架_第35张图片
JAVAweb之SSH框架_第36张图片
点击ok,
JAVAweb之SSH框架_第37张图片
下一步
JAVAweb之SSH框架_第38张图片
直接下一步
JAVAweb之SSH框架_第39张图片
点击后会出现如下
JAVAweb之SSH框架_第40张图片
选择yes
JAVAweb之SSH框架_第41张图片
到此步逆向工程就完成了。

接下来可以写一些类
business.basic包(放置基类及帮助类)
在这里插入图片描述
business.dao包(放置业务接口供给调用)
创建一个用户业务接口
JAVAweb之SSH框架_第42张图片
JAVAweb之SSH框架_第43张图片
选择interface,下一步
JAVAweb之SSH框架_第44张图片
点击finish,接口类就创建好了。
JAVAweb之SSH框架_第45张图片
UserDAO代码如下(一般书写登录及增删查改接口)

package business.dao;
import java.util.List;
import model.TUser;

public interface UserDAO {
	
	/**
	 * 用户登录业务方法
	 * @param userid   用户登录名
	 * @param password   登录密码
	 * @return  TUser  当前登录的用户对象
	 */
	public TUser login(String userid,String password);
	
	/**
	 * 普通用户的注册方法
	 * @param userid  用户注册的用户名
	 * @param password  用户注册录密码的的
	 * @param username  用户注册的姓名
	 * @return  boolean  注册成功返回true 失败返回false
	 */
	public boolean addNormalUser(String userid,String password,String username);

	/**
	 * 修改普通用户信息
	 * @param userid  要修改的用户的用户名
	 * @param password  修改后的密码
	 * @param username  修改后的用户网站昵称
	 * @return 修改成功返回true 失败返回false
	 */
	public boolean modifyNormalUser(String userid,String password,String username); 

	/**
	 * 根据用户输入的用户名返回对应的TUser对象
	 * @param userid 用户名
	 * @return TUser对象
	 */
	public TUser getTUserById(String userid);
	
	
	/**
	 * 判断注册用户名是否可用
	 * @param userid
	 * @return 用户名可用返回true, 否则返回false
	 */
	public boolean isValidateUserid(String userid);

	
}


business.impl包(放置接口实现类)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XTSG4bfP-1574340786841)(https://img-blog.c sdnimg.cn/20191121192641243.png)]
JAVAweb之SSH框架_第46张图片
JAVAweb之SSH框架_第47张图片
JAVAweb之SSH框架_第48张图片
JAVAweb之SSH框架_第49张图片
代码如下

package business.impl;

import java.util.List;
import model.TUser;
import business.basic.iHibBaseDAO;
import business.basic.iHibBaseDAOImpl;
import business.dao.UserDAO;

public class UserDAOImpl implements UserDAO {
	
private iHibBaseDAO bdao = null;
	
	public void setBdao(iHibBaseDAO bdao) {
		this.bdao = bdao;
	}

	public UserDAOImpl(){
		bdao = new iHibBaseDAOImpl();
	}
	

	@Override
	public TUser login(String userid, String password) {
		String hql="from TUser where userid = ? and password = ?";
		Object[] para = {userid,password};
		List list = bdao.select(hql, para);
		if(list.size()>0){
			return (TUser)list.get(0);
		}else {
			return null;
		}
	}

	@Override
	public boolean addNormalUser(String userid, String password, String username) {
		TUser user = new TUser();
		user.setUserid(userid);
		user.setPassword(password);
		user.setUsername(username);	
		Object obj = bdao.insert(user);
		if(obj != null){
			return true;
		}else {
			return false;
		}
	}


	@Override
	public boolean modifyNormalUser(String userid, String password,
			String username) {
		TUser user = (TUser)bdao.findById(TUser.class, userid);
		user.setPassword(password);
		user.setUsername(username);
		return bdao.update(user);
	}


	@Override
	public TUser getTUserById(String userid) {
		return (TUser)bdao.findById(TUser.class, userid);
	}

	@Override
	public boolean isValidateUserid(String userid) {
		TUser user = (TUser)bdao.findById(TUser.class, userid);
		if(user!=null && !user.getUserid().equals("")){
			return false;
		}else {
			return true;
		}
	}

	}

business.factory包(放置工厂类)
在这里插入图片描述
工厂里整合了接口和接口实现类,在action里直接调用工厂类,就不用再分开调用接口和接口实现,不用再下实例化对象在调用。
代码如下
动态工厂

package business.factory;
import business.dao.UserDAO;
import business.impl.UserDAOImpl;

/*
 * 动态工厂
 */
public class DAOFactory {

	
	/**
	 * 返回一个用于对用户信息操作的UserDAO对象
	 * @return UserDAO
	 */
	public UserDAO getUserDAO(){
		return new UserDAOImpl();
	}
	
}

动态工厂

package business.factory;
import business.dao.UserDAO;
import business.impl.UserDAOImpl;
public class StaticDAOFactory {
	
	/**
	 * (静态方法)返回一个用于对用户信息操作的UserDAO对象
	 * @return UserDAO
	 */
	public static UserDAO getUserDAO(){
		return new UserDAOImpl();
	}
	
}

一般选用动态。

spring配置
可创建bean来管理接口及接口实现(将接口及接口实现、工厂注册给bean,配置好后交给spring统一管理)也可直接在session工厂利配置
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
创建一个新springbean来注册管理,我们命名为bean1
在这里插入图片描述
选择other
JAVAweb之SSH框架_第50张图片
下一步
JAVAweb之SSH框架_第51张图片
选择sping链接(根据所需配置加载)
JAVAweb之SSH框架_第52张图片
JAVAweb之SSH框架_第53张图片
勾选如上复选框,点击Finish,springbean就创建好了。
接下来配置bean
这里讲一下静态工厂的方法注入
静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过spring注入的形式获取:





    
    
    
 
 
	
	
		
	
	 
	
		
	
	


工程项目下的web.xml的配置
JAVAweb之SSH框架_第54张图片
到此步springbean就配置成功了。

struts.xml配置
JAVAweb之SSH框架_第55张图片
为了更好的进行配置,我们选择视图界面配置
JAVAweb之SSH框架_第56张图片
建好后的视图界面
JAVAweb之SSH框架_第57张图片
首先我们先创建如下几个jsp和css文件
JAVAweb之SSH框架_第58张图片
接下来添加action
JAVAweb之SSH框架_第59张图片
JAVAweb之SSH框架_第60张图片
配置失败返回参数
JAVAweb之SSH框架_第61张图片
如果跳转到网页可以使用dispatcher,页面跟共用响应对象
redirect简单的重定位,不共用响应对象
redirectAction action跳转action,不共用响应对象

建立好的包视图
JAVAweb之SSH框架_第62张图片
看看他的配置文件
它的参数要在action里定义才会生效
JAVAweb之SSH框架_第63张图片
接下来就可以书写action了
打开新建好的LoginAction类
JAVAweb之SSH框架_第64张图片
公共封装方法命名为BaseAction如下

package business.action;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class BaseAction extends ActionSupport {
	protected  HttpServletRequest request;
	protected HttpServletResponse response;
	protected HttpSession session;
	protected ServletContext application;
	
	public BaseAction() {
		super();
		request = ServletActionContext.getRequest();
		response = ServletActionContext.getResponse();
		session = request.getSession();
		application = ServletActionContext.getServletContext();
	}
}

当struts接受这个action请求时,struts调用 username的get方法把前台的值传到action中的username,当action处理完成,要返回到页面时。在生成jsp的过程中,你可以在页面中使用EL表达式,${username}进行绑值,这时调用username的set方法。
 在jsp页面顶部导入el表达式标签连接

 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

JAVAweb之SSH框架_第65张图片
 LoginAction类

package business.action;

import model.TUser;
import business.dao.UserDAO;
import business.factory.DAOFactory;

public class LoginAction extends BaseAction {
	
	//获取jsp页面传过来的userid和password
	private String userid; 
	private String password;
	
	//利用get set方法将值获取上
	public String getUserid() {
		return userid;
	}

	public String getPassword() {
		return password;
	}
	
	public void setUserid(String userid) {
		this.userid = userid;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setErrorsText(String errorsText) {
		this.errorsText = errorsText;
	}

	public void setBackurl(String backurl) {
		this.backurl = backurl;
	}

	private String errorsText;//设置错误提示文字

	private String backurl; //返回地址
		
	public String getErrorsText() {
		return errorsText;
	}

	public String getBackurl() {
		return backurl;
	}
	
	private String requesturl;
		
		public String getRequesturl() {
			return requesturl;
		}
	
		public void setRequesturl(String requesturl) {
			this.requesturl = requesturl;
		}

	/**
	 * @return
	 */
	public String execute() {
		System.out.println("获取:用户名"+userid+"密码:"+password);
		
		backurl="login.jsp";

		//判断输入框是否为空
		if(userid==null ||userid.trim().equals("")){
			errorsText = "用户账号不能为空";
			return ERROR;
		}else if(password==null ||password.trim().equals("")){
			errorsText = "密码不能为空";
			return ERROR;
		}
		
		//以数据库数据进行对比
		UserDAO udao = new DAOFactory().getUserDAO();
		TUser loginUser = udao.login(userid, password);
		if(loginUser!=null && loginUser.getUsername()!=null){
			
			//判断登陆成功,将用户名存在session里供后续操作调用
			session.setAttribute("loginuser", loginUser);
			//记录当前地址
			requesturl = (String)session.getAttribute("requesturl");
			return SUCCESS;
			
		}else{
			//失败则跳转 fial.jsp
			errorsText = "登录失败";
			return ERROR;
		}
		
	}
}

success.jsp代码

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>






SSH









当前的登录用户为:${loginuser.username}

添加user,如果姓名没有冲突,那么就添加到数据库,如果姓名冲突了就不能添加,返回失败页面
UserName:
UserPassword:
UserMessage:
根据姓名查询,若不输入,则查询全部
UserName:
编号 姓名 信息 操作
${user.id} ${user.username} ${user.usermessage} 编辑 删除

fail.jsp代码


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>fail</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="fail">

</head>

<body>
    <div style="color:red;">fail</div><br/>
   <center>
		<p><h2>${errorsText}</h2></p>
		
		</center>
		 <div id = "foot">
    	<a href="${backurl}">返回上一页面</a>
    </div>
   <!--  <a href="query.action?queryText=">返回主页</a> -->
</body>
</html>

建立好如上,运行测试
输入为空测试
JAVAweb之SSH框架_第66张图片
输入账号密码测试
JAVAweb之SSH框架_第67张图片
输入后会报如上错误
经过一番上网查询测试,发现:
主要 是里面的Structs 1.3 (structs 2)和Hibernate 3.2(或更高版本)中的JAR包里antlr2.7.2 与 antlr2.7.6 冲突,只要删除Structs 1.3中的低版本的antlr2.7.2就可以了。具体操作如下:在MyEclipse 下,windows–>preferences–>在文本框中搜索struts2–>选择 antlr2.7.2–>remove
JAVAweb之SSH框架_第68张图片
现在重启Tomcat再次测试:
JAVAweb之SSH框架_第69张图片
现在登陆成功了,并且获取到了用户名。
在测试查询时,利用查询多条记录可以正常使用,但存在的单条记录会报错。如下
JAVAweb之SSH框架_第70张图片
经过小编多放查证,终于发现:
在访问某个页面出现了上标题所示的异常。一开始我也不知道什么原因,因为后台已经返回了数据,而且前端的el/jstl表达式都写的没毛病。
后来无意中想到,我这个数据是确定的只有一条,但是我还是用的来写。然后我把数据包装了一下,虽然只有一条数据,但是我返回的还是一个list集合就没问题啦(重新写了一个接口)
JAVAweb之SSH框架_第71张图片
改变后的action
JAVAweb之SSH框架_第72张图片
测试通过
JAVAweb之SSH框架_第73张图片
项目完整演示:
JAVAweb之SSH框架_第74张图片

注意

本项目的SSH框架中spring是以单spring框架搭建(单纯的整合hibernate数据库连接,其间的接口及其注入配置貌似没有什么作用,其实实配置不配置程序都能运行。)而在实际项目开发中多是spring与其他技术架构结合的,比如springMVC、springBoot等等。这些项目框架会在后续博文中给大家呈现。

项目中有什么错误之处,希望有心之人在评论中指出或私发消息讨论。

此项目用SSH框架搭建,实现了用户的登录、查询、删除、添加。
项目(源码+数据库)我已上传至gitee码云上,有需要的可以进行下载:
GITEE码云地址:https://gitee.com/zhangyant/SSHtest
记得更改hibernate数据库连接(导入sql文件夹中sql语句)。
JAVAweb之SSH框架_第75张图片
JAVAweb之SSH框架_第76张图片
JAVAweb之SSH框架_第77张图片
另一种ssh架构可参考:https://www.cnblogs.com/acm-bingzi/p/ssh.html
本人觉得此方法有点难以理解(–^^–)。

你可能感兴趣的:(Java,Web,应用,myeclipes,javaweb,SSH框架)