一、目的:
- 使初学者能更好的去了解SSH框架。
- 给以后的自己,也给别人一个参考。
- 尝试搭建一个完整的SSH框架项目。
二、SSH三大框架的概述
Struts + Spring + Hibernate三者各自的特点都是什么?
Struts 的MVC设计模式可以使我们的逻辑变得很清晰,主要负责表示层的显示。
Spring 的IOC和AOP可以使我们的项目在最大限度上解藕。
hibernate的就是实体对象的持久化了, 数据库的封装。
表现层、中间层(业务逻辑层)和数据服务层。三层体系将业务规则、数据访问及合法性校验等工作放在中间层处理。客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与数据库交互。
表现层是传统的JSP技术。
中间层采用的是流行的Spring+Hibernate,为了将控制层与业务逻辑层分离,又细分为以下几种。
Web层,就是MVC模式里面的“C”(controller<action>),负责控制业务逻辑层与表现层的交互,调用业务逻辑层,并将业务数据返回给表现层作组织表现,该系统的MVC框架采用Struts。
Service层(就是业务逻辑层),负责实现业务逻辑。业务逻辑层以DAO层为基础,通过对DAO组件的正面模式包装,完成系统所要求的业务逻辑。
DAO层,负责与持久化对象交互。该层封装了数据的增、删、查、改的操作。
PO,持久化对象。通过实体关系映射工具将关系型数据库的数据映射成对象,很方便地实现以面向对象方式操作数据库。
Spring的作用贯穿了整个中间层,将Web层、Service层、DAO层及PO无缝整合,其数据服务层用来存放数据。
三、项目实战案例
创建项目有两种方式:web动态项目及maven项目(建议使用maven创建项目)。
创建web动态工程注意classpath路径
导入本次项目要使用到的jar包:
struts:http://struts.apache.org/
hibernate:https://sourceforge.net/projects/hibernate/files/latest/download?source=files (访问就提示下载,无需做其它操作)
在lib文件夹下添加相关jar包依赖(建议使用maven创建项目,便于jar包管理,避免jar版本冲突)
相关配置文件:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ssh</display-name> <!-- 将Spring配置到web项目中 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 将struts配置到web项目中 --> <filter> <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> |
spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- 自动处理静态资源文件 --> |
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- context 注解 --> <!-- tx 事务--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启注解 --> <context:annotation-config/> <!-- 指定哪些包下受baen管制 --> <context:component-scan base-package="com.blog"></context:component-scan> <!-- 数据源(数据库) --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="jdbc:mariadb://localhost:3300/blog"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 配置SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- 扩展使用Hibernate原生的配置 --> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.MariaDB53Dialect</prop> <prop key="show_sql">true</prop> </props> </property> <!-- 映射实体类(Entity) --> <property name="packagesToScan" value="com.blog.blog.entity, com.blog.admin.entity"/> </bean> <!-- 事务层 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 事务注解 --> <tx:annotation-driven/> <!-- 开启aop --> <aop:aspectj-autoproxy/> </beans> |
struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package namespace="/" name="default" extends="struts-default"> <!-- 设置和配置action的拦截器 --> <interceptors> <interceptor name="loginInterceptor" class="com.blogAdmin.action.articleTpye.LoginInterceptorAction"></interceptor> </interceptors> <!-- 定义为全局结果,这样action和result都能访问 --> <global-results> <result name="loginRedirect" type="redirectAction">loginPage</result> </global-results> <!-- 登陆成功跳转的页面 --> <action name="list" class="com.blogAdmin.action.articleTpye.ListAction"> <interceptor-ref name="defaultStack"></interceptor-ref> <!-- 系统默认拦截器 --> <interceptor-ref name="loginInterceptor"></interceptor-ref> <!-- 自己定义的拦截器 --> <!-- 首页面 --> <result name="list">/WEB-INF/jsp/articleType/list.jsp</result> </action> </package> </struts> |
后台代码(部分,不完整)
Entity层(具体根据数据库表及字段进行创建相应实体类)
初始化Hibernate的entity
package com.blogAdmin.init;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
public class HibernateInit extends HttpServlet {
private static final long serialVersionUID = 1L;
public static SessionFactory sf;
@Override
public void init() throws ServletException {
super.init();
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
sf = new MetadataSources(registry).buildMetadata().buildSessionFactory();
}
}
dao层
userDao类
package com.blogAdmin.dao;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.query.Query;
import com.opensymphony.xwork2.ActionSupport;
import com.blogAdmin.entity.Article;
import com.blogAdmin.entity.User;
import com.blogAdmin.init.HibernateInit;
/**
* 用户登陆的dao
* @author admin
*
*/
public class UserDao extends ActionSupport implements Serializable {
private static final long serialVersionUID = -9124089639234157594L;
public User findByUserName(String username){
Session session = HibernateInit.sf.openSession();
String hql = "from User where username=?";
Query<User> dbUser = session.createQuery(hql,User.class);
dbUser.setParameter(0, username);
return dbUser.uniqueResult();
}
public Article getByUser(String id){
Article article = null;
Session session = HibernateInit.sf.openSession();
article = session.get(Article.class, id);
session.close();
return article;
}
}
(增删改查)dao层
package com.blogAdmin.dao;
import java.math.BigInteger;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import com.blogAdmin.entity.Article;
import com.blogAdmin.init.HibernateInit;
import com.blogAdmin.vo.ArticleVo;
public class ArticleDao {
/**
* 添加
* @param article
*/
public void save(Article article) {
Session session = HibernateInit.sf.openSession();
Transaction ts = session.beginTransaction();
session.save(article);
ts.commit();
session.close();
}
/**
* 删除
* @param id
*/
public void delete(String id) {
Session session = HibernateInit.sf.openSession();
Transaction ts = session.beginTransaction();
String hql = "delete from Article where id=?";
session.createQuery(hql).setParameter(0, id).executeUpdate();
ts.commit();
session.close();
}
/**
* 修改
* @param article
*/
public void update(Article article) {
Session session = HibernateInit.sf.openSession();
Transaction ts = session.beginTransaction();
session.update(article);
ts.commit();
session.close();
}
/**
* 分页查询
* @param pageNum
* @param pageSize
* @return
*/
public List<ArticleVo> pageList(int pageNum, int pageSize) {
List<ArticleVo> returnList = null;
Session session = HibernateInit.sf.openSession();
Query<ArticleVo> query = session.createNativeQuery("select a.*,u.username name,t.name articleType from article a join user u join article_type t on a.user_id=u.id and a.type_id=t.id order by a.create_time",ArticleVo.class);
query.setFirstResult((pageNum - 1) * pageSize);
query.setMaxResults(pageSize);
returnList = query.list();
session.close();
return returnList;
}
/**
* 获取总条数
* @return
*/
public BigInteger totalCount() {
BigInteger totalCount = new BigInteger("0");
Session session = HibernateInit.sf.openSession();
totalCount = (BigInteger) session.createNativeQuery("select count(id) from article").uniqueResult();
session.close();
return totalCount;
}
/**
* 根据id查询一条数据
* @param typeId
* @return
*/
public Article getById(String id){
Article article = null;
Session session = HibernateInit.sf.openSession();
article = session.get(Article.class, id);
session.close();
return article;
}
}
service<接口>及serviceImpl<实现类>层
略
action层
LoginAction类
package com.blogAdmin.action.articleTpye;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
import com.blogAdmin.dao.UserDao;
import com.blogAdmin.entity.User;
import com.blogAdmin.vo.UserVo;
/**
* 登陆页面的action
* @author admin
*
*/
@Results({@Result(location="/WEB-INF/jsp/login.jsp"),
@Result(name="list",type="redirectAction",location="list"),
@Result(name="loginPage",type="redirectAction",location="loginPage")})
public class LoginAction extends ActionSupport implements ServletRequestAware{
private static final long serialVersionUID = 6690219852711831094L;
private HttpSession session; //获取session对象,将UserVo对象存入session
private UserVo userVo;
public UserVo getUserVo() {
return userVo;
}
public void setUserVo(UserVo userVo) {
this.userVo = userVo;
}
/**
* 1,打开登陆页面
*/
@Action("/loginPage")
public String loginPage() {
return SUCCESS;
}
/**
*2,登陆按钮action
* @return
*/
@Action("/login")
public String login(){
//判断是否为空
String name = userVo.getUsername();
String pass = userVo.getPassword();
if(name==null||"".equals(name)&&pass==null||"".equals(pass)){
session.setAttribute("msg", "用户名或密码不能为空!");
return "loginPage";
}
UserDao dao = new UserDao();
User user = dao.findByUserName(userVo.getUsername());
if(user==null){
session.setAttribute("msg", "用户名或密码不正确!");
return "loginPage";
}
if (!user.getPassword().equals(pass)) {
session.setAttribute("msg", "用户名或密码不正确!");
return "loginPage";
}
session.setAttribute("userVo", userVo);
return "list";
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.session = request.getSession();
}
}
LoginInterceptorAction类
package com.blogAdmin.action.articleTpye;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LoginInterceptorAction implements Interceptor{
private static final long serialVersionUID = -7254285326542480257L;
@Override
public void destroy() {
}
@Override
public void init() {
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpSession session = ServletActionContext.getRequest().getSession(); //通过struts的上下文,获取到session对象
Object userVo = session.getAttribute("userVo");
if (userVo==null) {
return "loginRedirect"; //如果为空,重定向到login页面;
}
return invocation.invoke();
}
}
PageAction相关类
package com.blogAdmin.action.articleTpye;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionSupport;
import com.blogAdmin.dao.ArticleTypeDao;
import com.blogAdmin.entity.ArticleType;
@Results({ @Result(name = "typeSave", location = "/WEB-INF/jsp/articleType/save.jsp"),
@Result(name="updateType", location = "/WEB-INF/jsp/articleType/update.jsp"),
@Result(name="redirectTypeSave",type="redirectAction",location="typeSave"),
@Result(name="redirectList",type="redirectAction",location="list"),
@Result(name = "list", location = "/WEB-INF/jsp/articleType/list.jsp")
})
public class ArticleTypeAction extends ActionSupport {
private static final long serialVersionUID = 6780775618333937202L;
//添加
private String typeName;
//分页
private int pageNum;
private int pageSize=10;
//删除
private String typeId;
//修改时的对象
ArticleType articleType;
/**
* 文章列表
* @return
*/
@Action("/articleType/list")
public String list(){
ArticleTypeDao dao = new ArticleTypeDao();
ServletActionContext.getRequest().setAttribute("list", dao.pageList(pageNum, pageSize));
ServletActionContext.getRequest().setAttribute("totalCount", dao.totalCount());
return "list";
}
/**
* 进入添加页面
* @return
*/
@Action("/articleType/typeSave")
public String typeSave() {
return "typeSave";
}
/**
* 点击保存(添加分类)
* @return
*/
@Action("/articleType/save")
public String save() {
ArticleTypeDao dao = new ArticleTypeDao();
dao.save(typeName);
return "redirectList";
}
/**
* 删除页面
* @return
*/
@Action("/articleType/delete")
public void delete(){
ArticleTypeDao dao = new ArticleTypeDao();
dao.delete(typeId);
}
/**
* 进入编辑页面
* @return
*/
@Action("/articleType/updateType")
public String updateType(){
ArticleTypeDao dao = new ArticleTypeDao();
ServletActionContext.getRequest().setAttribute("articleType", dao.getById(typeId));
return "updateType";
}
/**
* 点击修改
* @return
*/
@Action("/articleType/update")
public String update() {
ArticleTypeDao dao = new ArticleTypeDao();
dao.update(articleType);
return "redirectList";
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public ArticleType getArticleType() {
return articleType;
}
public void setArticleType(ArticleType articleType) {
this.articleType = articleType;
}
}
IndexAction类
package com.blogAdmin.action.articleTpye;
import com.opensymphony.xwork2.ActionSupport;
/**
* 登陆成功后展示的页面
* @author admin
*
*/
public class ListAction extends ActionSupport{
private static final long serialVersionUID = -7248676355265672252L;
/**
* 首页面
* @return
*/
@Override
public String execute() throws Exception {
return "list";
}
}