maven ssh mysql_基于Maven构建ssh项目

源码下载:点我

一、数据库准备

1.创建数据库maven

create database maven character set utf8 collate utf8_general_ci; //use maven;

2.创建用户表

create table t_users(

id int primary key auto_increment,

username varchar(30) not null,

password varchar(50) not null,

constraint unq_users_username unique(username)

);

3.插入测试数据

insert into t_users(username,password) values('admin', md5('admin'));

insert into t_users(username,password) values('user', md5('user'));

二、项目构建

1.创建简单Maven项目

2.在webapps下创建WEB-INF目录,并在WEB-INF下创建web.xml,

3.复制porm.xml文件内容(jar包的准备)

4.右击项目-->Maven-->Update Project(解决eclipse报错)

三、Dao层构建

1.编写实体类User.java(可以使用Hibernate反向工程)

package com.hao.entity;

// Generated 2017-8-6 12:57:28 by Hibernate Tools 4.0.0

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import static javax.persistence.GenerationType.IDENTITY;

import javax.persistence.Id;

import javax.persistence.Table;

import javax.persistence.UniqueConstraint;

/**

* TUsers generated by hbm2java

*/

@Entity

@Table(name = "t_users", catalog = "maven", uniqueConstraints = @UniqueConstraint(columnNames = "username"))

public class User implements java.io.Serializable {

private static final long serialVersionUID = 1L;

private Integer id;

private String username;

private String password;

public User() {

}

public User(String username, String password) {

this.username = username;

this.password = password;

}

@Id

@GeneratedValue(strategy = IDENTITY)

@Column(name = "id", unique = true, nullable = false)

public Integer getId() {

return this.id;

}

public void setId(Integer id) {

this.id = id;

}

@Column(name = "username", unique = true, nullable = false, length = 30)

public String getUsername() {

return this.username;

}

public void setUsername(String username) {

this.username = username;

}

@Column(name = "password", nullable = false, length = 50)

public String getPassword() {

return this.password;

}

public void setPassword(String password) {

this.password = password;

}

}

2.Dao层代码抽取以及UserDao的编写

2.1 BaseDao接口

package com.hao.dao.base;

import java.io.Serializable;

import java.util.List;

public interface BaseDao {

void save(T entity);

void delete(T entity);

void deleteById(Serializable id);

void update(T entity);

T findById(Serializable id);

List findAll();

}

2.2 BaseDaoImpl实现类

package com.hao.dao.base.impl;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.List;

import org.hibernate.SessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import com.hao.dao.base.BaseDao;

public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao {

private Class entityClass;

@SuppressWarnings("unchecked")

public BaseDaoImpl() {

//获取子类对象的父类类型

ParameterizedType superClass = (ParameterizedType) this.getClass().getGenericSuperclass();

//获得在父类类型上声明的反省数组

Type[] genericTypes = superClass.getActualTypeArguments();

//第一个泛型即为实体类型

entityClass = (Class) genericTypes[0];

}

@Override

public void save(T entity) {

getHibernateTemplate().save(entity);

}

@Override

public void delete(T entity) {

getHibernateTemplate().delete(entity);

}

@Override

public void deleteById(Serializable id) {

T entity = getHibernateTemplate().load(entityClass, id);

getHibernateTemplate().delete(entity);

}

@Override

public void update(T entity) {

getHibernateTemplate().update(entity);

}

@Override

public T findById(Serializable id) {

return getHibernateTemplate().get(entityClass, id);

}

@Override

public List findAll() {

return getHibernateTemplate().loadAll(entityClass);

}

/**

* HibernateDao接口在使用前必须注入SessionFactory

* @param sessionFactory

*/

@Autowired

public void setSF(SessionFactory sessionFactory){

super.setSessionFactory(sessionFactory);

}

}

2.3 UserDao接口

package com.hao.dao;

import com.hao.dao.base.BaseDao;

import com.hao.entity.User;

public interface UserDao extends BaseDao{

User login(String username, String password);

}

2.4 UserDaoImpl实现类

package com.hao.dao.impl;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.hao.dao.UserDao;

import com.hao.dao.base.impl.BaseDaoImpl;

import com.hao.entity.User;

@Repository("userDao")

public class UserDaoImpl extends BaseDaoImpl implements UserDao{

@Override

public User login(String username, String password) {

@SuppressWarnings("unchecked")

List user = (List) getHibernateTemplate().find("from User u where u.username=? and u.password=?", username, password);

if(user == null || user.size() < 1){

return null;

}else{

return user.get(0);

}

}

}

2.5 导入MD5工具类,Dao的单元测试和Service层要使用

package com.hao.utils;

import java.math.BigInteger;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

public class MD5Utils {

/**

* 使用md5的算法进行加密

*/

public static String md5(String plainText) {

byte[] secretBytes = null;

try {

secretBytes = MessageDigest.getInstance("md5").digest(

plainText.getBytes());

} catch (NoSuchAlgorithmException e) {

throw new RuntimeException("没有md5这个算法!");

}

String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字

// 如果生成数字未满32位,需要前面补0

for (int i = 0; i < 32 - md5code.length(); i++) {

md5code = "0" + md5code;

}

return md5code;

}

public static void main(String[] args) {

System.out.println(md5("123"));

}

}

3.注意BaseDao继承的HibernateDaoSupport要选择正确的包,其有分hibernate3,hibernate4和hibernate5,导错包会抛异常

四、配置spring-dao基础

1.在applicationContext.xml中配置Spring组件扫描

2.在applicationContext.xml中配置数据源

3.编写db.properties文件,存放在类路径下

jdbc.jdbcUrl=jdbc:mysql://localhost:3306/maven

jdbc.driverClass=com.mysql.jdbc.Driver

jdbc.user=root

jdbc.password=h66666

五、Spring整合Hibernate

1.在applicationContext.xml中配置SessionFactory,注意class属性也要选择正确的包

org.hibernate.dialect.MySQLDialect

true

true

update

2.在applicationContext.xml中配置核心事务管理器

3.开启注解事务(也可以使用声明式事务)

4.由于我采用注解定义Hibernate实体类,因此映射注解元数据使用的是packagesToScan属性

5.如果使用的是hbm.xml文件映射元数据,可以使用mappingLocations(建议)或mappingDirectoryLocations

六、配置log4j日志环境

以下为log4j.properties的内容:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.appender.file=org.apache.log4j.FileAppender

log4j.appender.file.File=D:\\temp\\mylog.log

log4j.appender.file.layout=org.apache.log4j.PatternLayout

log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### fatal error warn info debug debug trace

log4j.rootLogger=debug, stdout

#log4j.logger.org.hibernate=INFO

#log4j.logger.org.hibernate.type=INFO

七、DAO层单元测试

1.注意,由于Spring的事务配置Service层,因此Dao层不具有事务性,因此单元测试必须添加@Transactional注解

2.经过测试,dao层的单元测试默认会执行事务回滚(不知为何,可能是因为没有配置@Transaction注解的参数?)

3.若想要不进行回滚而在数据库看到结果(如插入等),需添加@Rollback(false)

4.UserDao的测试代码

package com.hao.dao;

import junit.framework.Assert;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.annotation.Rollback;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.transaction.annotation.Transactional;

import com.hao.entity.User;

import com.hao.utils.MD5Utils;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={"classpath:applicationContext.xml"})

@Transactional

@Rollback(false)

public class UserDaoTest {

@Autowired

UserDao userDao;

@Test

public void testLogin(){

Assert.assertNotNull(userDao.login("admin", MD5Utils.md5("admin")));

Assert.assertNull(userDao.login("admin", MD5Utils.md5("pass")));

Assert.assertNotNull(userDao.login("user", MD5Utils.md5("user")));

}

@Test

public void testSave(){

User u = new User();

u.setUsername("dao");

u.setPassword("dao");

userDao.save(u);

}

}

八、编写Service层代码

1.UserService接口

package com.hao.service;

import com.hao.entity.User;

public interface UserService {

User login(User user);

void save(User user);

}

2.UserServiceImpl实现类,要求使用注解配置事务

package com.hao.service.impl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Isolation;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

import com.hao.dao.UserDao;

import com.hao.entity.User;

import com.hao.service.UserService;

import com.hao.utils.MD5Utils;

@Service("userService")

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = true)

public class UserServiceImpl implements UserService{

private UserDao userDao;

@Autowired

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

@Override

public User login(User user) {

String pass = MD5Utils.md5(user.getPassword());

return userDao.login(user.getUsername(), pass);

}

@Override

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)

public void save(User user) {

userDao.save(user);

}

}

九、编写Service层的单元测试

1.由于Service配置了Spring的事务,因此基于Service的单元测试无需再添加@Transactional注解

2.经测试,Service层的单元测试默认不具有回滚性(可能与@Transaction注解有关)

3.并且,即使在测试类上添加注解@rollback(true)注解也无法回滚(不知原因)

4.UserService测试代码

package com.hao.service;

import junit.framework.Assert;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.annotation.Rollback;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.hao.entity.User;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

@Rollback(true)

public class UserServiceTest {

@Autowired

UserService userService;

@Test

public void testLogin(){

User u1 = new User();

u1.setUsername("admin");

u1.setPassword("admin");

User u2 = new User();

u2.setUsername("admin");

u2.setPassword("pass");

User u3 = new User();

u3.setUsername("user");

u3.setPassword("user");

Assert.assertNotNull(userService.login(u1));

Assert.assertNull(userService.login(u2));

Assert.assertNotNull(userService.login(u3));

}

@Test

public void testSave(){

User u = new User();

u.setUsername("service");

u.setPassword("service");

userService.save(u);

}

}

十、Action层的抽取以及编写UserAction

1.抽取BaseAction

package com.hao.action.base;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

public class BaseAction extends ActionSupport implements ModelDriven, RequestAware, SessionAware{

private static final long serialVersionUID = 1L;

protected Map request;

protected Map session;

protected T model;

@Override

public void setRequest(Map request) {

this.request = request;

}

@Override

public void setSession(Map session) {

this.session = session;

}

@Override

public T getModel() {

return model;

}

public BaseAction() {

//获取父类

ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();

//获取父类的泛型数组

Type[] types = genericSuperclass.getActualTypeArguments();

//取得第一个泛型,即Model的类型

@SuppressWarnings("unchecked")

Class entityClass = (Class) types[0];

try {

model = entityClass.newInstance();

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

2.UserAction代码编码,继承于BaseAction

package com.hao.action;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Scope;

import org.springframework.stereotype.Controller;

import com.hao.action.base.BaseAction;

import com.hao.entity.User;

import com.hao.service.UserService;

@Controller("userAction")

@Scope("prototype")

public class UserAction extends BaseAction{

private static final long serialVersionUID = 1L;

public String login(){

System.out.println("-------------------------------------------------------"+this);

User user = userService.login(model);

if(user == null){

request.put("errorInfo", "用户名或密码错误");

return LOGIN;

}

session.put("loginUser", user);

return SUCCESS;

}

@Autowired

private UserService userService;

public UserService getUserService() {

return userService;

}

public void setUserService(UserService userService) {

this.userService = userService;

}

}

十一、配置struts2,并整合到Spring

1.在web.xml中配置struts2过滤器

struts2

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

struts2

/*

2.配置struts.xml,其中Action的类名写成Spring中定义的实体名(Spring与Struts2的整合)

/p>

"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

"http://struts.apache.org/dtds/struts-2.3.dtd">

/success.jsp

/index.jsp

3.注意将struts2整合到Spring时,Action的scope必须为prototype,采用bean的prototy属性或者@Scope注解进行配置

4.为什么必须是prototype?这是由struts2的架构所决定的!

十二、(可选)如果Action是以解耦方式编写的(即不依赖容器产生HttpServletRequest和HttpServletResponse),还可以对Action层进行单元测试

1.对Action层做单元测试相当于模拟一次请求而进行对应的方法调用

2.对Action进行单元测试的前提是,在对Action进行编码时,采用解耦方式获取request,response,session等(即拿到的是一个Map),这样就不需要Servlet便可以执行测试

3.UserAction测试代码

package com.hao.action;

import java.util.HashMap;

import java.util.Map;

import junit.framework.Assert;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationCOntext.xml")

public class UserActionTest {

@Autowired

UserAction userAction;

@Before

public void init(){

//模拟容器,提供Request和Session

Map request = new HashMap();

Map session = new HashMap();

userAction.setRequest(request);

userAction.setSession(session);

}

@Test

public void testLogin(){

//模拟提供请求参数

userAction.getModel().setUsername("admin");

userAction.getModel().setPassword("admin");

//模拟一次登录请求

Assert.assertEquals(UserAction.SUCCESS, userAction.login());

//模拟提供请求参数

userAction.getModel().setUsername("admin");

userAction.getModel().setPassword("pass");

//模拟错误的用户名密码登录请求

Assert.assertEquals(UserAction.LOGIN, userAction.login());

}

}

十三、Spring整合到Web环境

1.在web.xml配置Spring上下文随Web上下文启动而启动

org.springframework.web.context.ContextLoaderListener

contextConfigLocation

classpath:applicationContext.xml

2.扩展Session的作用域到请求结束(web.xml),注意选择正确的Hibernate版本,而且注意要配置在struts2过滤器之前

openSessionInView

org.springframework.orm.hibernate5.support.OpenSessionInViewFilter

openSessionInView

/*

十四、编写页面,启动项目

1.编写index.jsp,注意引入jstl标签库

用户名:

密 码:

2.编写success.jsp

${sessionScope.loginUser.username }登陆成功

3.启动项目,访问index.jsp观察结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值