1. pageModel
1.1 User.java:注意与数据表Tuser有区别
其内容很大程度上是有表单内容决定的
public class User implements java.io.Serializable {
private String id;
private String name;
private String pwd;
private Date creatTime;
private Date endTime;
private int page;
private int rows;
private String sort;
private String order;
private String ids;
}
1.2 Menu.java
public class Menu {
private String state;//应对EasyUI所需要的json数据,建立的属性
private String pid; //对应父类
private Tmenu ptext;//对应父类的名字
private String id;
private String text;
private String iconcls;
private String url;
private Map<String,Object> attributes;
}
2. BaseDaoImpl.java
@Repository("baseDao")
public class BaseDaoImpl<T> implements BaseDao<T> {
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session getMySession() {
return this.sessionFactory.getCurrentSession();
}
@Override
public Serializable save(T o) {
return sessionFactory.getCurrentSession().save(o);
}
@Override
public T get(String hql) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
@SuppressWarnings("unchecked")
List<T> l = q.list();
if (l != null && l.size() > 0)
return l.get(0);
return null;
}
@Override
public T get(String hql, Object[] params) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++)
q.setParameter(i, params[i]);
}
@SuppressWarnings("unchecked")
List<T> l = q.list();
if (l != null && l.size() > 0)
return l.get(0);
return null;
}
@Override
public T get(String hql, Map<String, Object> params) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
// ★这里可以用map循环对应赋值,那样就不要知道具体的参数值(如name和pwd)
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
@SuppressWarnings("unchecked")
List<T> l = q.list();
if (l != null && l.size() > 0)
return l.get(0);
return null;
}
@Override
public void delete(T o) {
this.getMySession().delete(o);
}
@Override
public void update(T o) {
this.getMySession().update(o);
}
@Override
public void saveOrUpdate(T o) {
this.getMySession().saveOrUpdate(o);
}
@Override
public List<T> getAll(String hql) {
Query q = this.getMySession().createQuery(hql);
return q.list();
}
@SuppressWarnings("unchecked")
@Override
public List<T> getAll(String hql, Map<String, Object> params) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return q.list();
}
@SuppressWarnings("unchecked")
@Override
/**分页查询
* @param hql
* @param params
* @param page 当前页数
* @param row 每页显示的条数
* @return
*/
public List<T> getPage(String hql, Map<String, Object> params, int page, int rows) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
// ★★分页查询功能:从第几条开始查询,查多少条
// 公式:(当前页-1)*每页显示的记录数
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}
@SuppressWarnings("unchecked")
@Override
/**
* 分页但是不传参
*/
public List<T> getPage(String hql, int page, int rows) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}
@Override
/**
* 查询记录的总条数,分页时显示总条数
*/
public Long count(String hql) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
// ★★查询到的结果始终是一个数的时候用
return (Long) q.uniqueResult();
}
@Override
/**
* 有参数的情况
*/
public Long count(String hql, Map<String, Object> params) {
Query q = this.sessionFactory.getCurrentSession().createQuery(hql);
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
q.setParameter(key, params.get(key));
}
}
return (Long) q.uniqueResult();
}
@Override
public T get(Serializable id, Class<T> clazz) {
return (T) this.getMySession().get(clazz, id);
}
@Override
/**
* 直接执行hql语句
*/
public int executeHql(String hql) {
Query q = this.getMySession().createQuery(hql);// 注意不能用creatSQLQuery()
return q.executeUpdate();
}
}
3 Service
该部分主要主要怎样拼接动态的Hql语句
3.1 UserServiceImpl
@Service(value = "userService")
@Transactional
// 注解方式:配置事务,注意是在service层配置,不是在dao层配置(★★缺点,这个类中的所有方法都配置了事务)
public class UserServiceImpl implements UserService {
private static final Logger logger = Logger.getLogger(UserServiceImpl.class);
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void test() {
// System.out.println("I am testing");
logger.info("I am testing");
}
public Serializable save(Tuser t) {
return userDao.save(t);
}
@Override
public void add(String name, String pwd) {
Tuser t = new Tuser();
t.setId(UUID.randomUUID().toString());
t.setPwd(pwd);
t.setCreatTime(new Date());
t.setName("hyc");
userDao.save(t);
}
@Override
public User save(User user) {
// ▲注意点:如果向add()方法中一样,用set方法,则如果对象有100个属性,则这里要set*Xxx()100次
// ★解决方案:使用BeanUtils类中的copyProperties()方法
Tuser t = new Tuser();
// 扩展:copyProperties()方法还可以使用第三个参数,刨除属性组成的数组
BeanUtils.copyProperties(user, t, new String[] { "pwd" });
t.setId(UUID.randomUUID().toString());
t.setCreatTime(new Date());
t.setPwd(MD5Util.encode(user.getPwd()));
userDao.save(t);
BeanUtils.copyProperties(t, user);
return user;
}
@Override
public User login(User user) {
// 拼接字符串的方式不好
// Tuser t =
// userDao.get("from Tuser t where t.name='"+user.getName()+"' and pwd='"+MD5Util.encode(user.getPwd())+"'");
// ★下面是改进方法(BaseDao中有相应的改变)
// Tuser t = userDao.get("from Tuser t where t.name=? and t.pwd =?", new
// Object[]{user.getName(),MD5Util.encode(user.getPwd())});
// 第三种方法
Map<String, Object> params = new HashMap<String, Object>();
params.put("name", user.getName());
params.put("pwd", MD5Util.encode(user.getPwd()));
;
Tuser t = userDao.get("from Tuser t where t.name= :name and t.pwd = :pwd", params);
if (t != null)
return user;
return null;
}
/**
* 带有查询功能
*/
@Override
/***/
public DataGrid datagrid(User user) {
DataGrid dg = new DataGrid();
String hql = "from Tuser t ";
// 添加sql语句的where条件
Map<String, Object> params = new HashMap<String, Object>();
hql = addWhereCond(user, hql, params);
// 用于分页的sql语句
String totalHql = "select count(*) " + hql;
// 前台有排序方式传过来才组织sql语句
if (user.getSort() != null) {
hql += " order by " + user.getSort() + " " + user.getOrder();// 确定页面数据排序方式
}
// 通过hql语句查询model
List<Tuser> tuserL = userDao.getPage(hql, params, user.getPage(), user.getRows());
List<User> userL = new ArrayList<User>();
tuserL2userL(tuserL, userL);
dg.setRows(userL);
dg.setTotal(userDao.count(totalHql, params));
return dg;
}
/**
* 完成Tuser->User的模型转换
*/
private void tuserL2userL(List<Tuser> tuserL, List<User> userL) {
if (tuserL != null && tuserL.size() > 0) {
for (Tuser t : tuserL) {
User u = new User();
BeanUtils.copyProperties(t, u);
userL.add(u);
}
}
}
/**
* 依据查询条件,动态sql语句的where部分
*/
private String addWhereCond(User user, String hql, Map<String, Object> params) {
// 依据name条件查询
if (user.getName() != null && !user.getName().trim().equals("")) {
hql += " where t.name like :name";
params.put("name", "%%" + user.getName().trim() + "%%");// ★%%才表示模糊匹配
}
// ★依据Id条件查询:这样相加什么条件就加什么条件
if (user.getId() != null && !user.getId().trim().equals("")) {
hql += " where t.id like :id";
params.put("name", "%%" + user.getId().trim() + "%%");
}
return hql;
}
@Override
public void remove(String ids) {
/*
* for(String id:ids.split(",")){ Tuser u = userDao.get(id, Tuser.class);
* if(u!=null){//这样一条条的删除,效率非常低 userDao.delete(u); } }
*/
//拼接hql语句,一次删除所有数据
String[] nids = ids.split(",");
String hql = "delete Tuser t where t.id in(";
for (int i = 0; i < nids.length; i++) {
if (i > 0) {
hql += ",";
}
hql += "'" + nids[i] + "'";
}
hql += ")";
userDao.executeHql(hql);
}
@Override
public User edit(User user) {
Tuser t = userDao.get(user.getId(), Tuser.class);
//第三个参数时刨除的意思
BeanUtils.copyProperties(user, t,new String[]{"id","pwd"});
//在事务结束的时候hibernate自动提交事务,即完成update方法
return user;
}
}
3.2 MenuServiceImpl
@Service(value = "menuService")
public class MenuServiceImpl implements MenuService {
private MenuDao menuDao;
public MenuDao getMenuDao() {
return menuDao;
}
@Autowired
// 如果将@Autowired写在"private MenuDao menuDao;"上面,则会将MenuDao变成公开属性
public void setMenuDao(MenuDao menuDao) {
this.menuDao = menuDao;
}
@Override
/**
* 由于OpenSessionView的作用,这里虽然只查询根节点,但是结果将会查询出来所有节点(Hibernate的级联查询)
*/
public List<Menu> getTree(String id) {
List<Menu> menuL = new ArrayList<Menu>();
String hql = "";
Map<String, Object> params = new HashMap<String, Object>();
if (id == null || id.equals("")) {
// 查询所有根节点
hql = "from Tmenu t where t.tmenu is null";
} else {
// 异步加载当前id下的子节点
hql = "from Tmenu t where t.tmenu.id =:id";
}
List<Tmenu> tmenuL = menuDao.getAll(hql, params);
if (tmenuL != null && tmenuL.size() > 0) {
for (Tmenu t : tmenuL) {
Menu m = new Menu();
BeanUtils.copyProperties(t, m);
// ★在pageModel中添加相关属性,这就是有个中间转换用的Model的好处
// 首先判断是否有子节点
// if (t.getTmenus() != null && !t.getTmenus().isEmpty()) {//get两次不是很好,用下面的方式
Set<Tmenu> set = t.getTmenus();
if (set != null && !set.isEmpty()) {
m.setState("closed");// 节点显示为文件夹形式
} else {
m.setState("open");
}
menuL.add(m);
}
}
return menuL;
}
@Override
public List<Menu> getAllNode4Tree() {
List<Menu> menuL = new ArrayList<Menu>();
String hql = "from Tmenu t";
List<Tmenu> tmenuL = menuDao.getAll(hql);
if (tmenuL != null && tmenuL.size() > 0) {
for (Tmenu t : tmenuL) {
Menu m = new Menu();
BeanUtils.copyProperties(t, m);
Map<String,Object> attributes = new HashMap<String, Object>();
attributes.put("url",t.getUrl());//
m.setAttributes(attributes);
Tmenu tm = t.getTmenu();// 获得当前节点的父节点对象
if (tm != null) {// 有父节点
m.setPid(t.getTmenu().getId());
}
menuL.add(m);
}
}
return menuL;
}
}
3.3 RepairServiceImpl.java
@Service(value="repairService")
public class RepairServiceImpl implements RepairService {
private BaseDao<Tmenu> menuDao;
private UserDao userDao;
public BaseDao<Tmenu> getMenuDao() {
return menuDao;
}
@Autowired
public void setMenuDao(BaseDao<Tmenu> menuDao) {
this.menuDao = menuDao;
}
public UserDao getUserDao() {
return userDao;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void repair() {
repairUser();
repairMenu();
}
/**
* ★★修复超级管理员
*/
private void repairUser() {
Map<String,Object> m = new HashMap<String, Object>();
m.put("name","admin");
Tuser t = userDao.get("from Tuser t where t.name=:name and t.id !='0'",m);
if(t!=null){
t.setName(UUID.randomUUID().toString());
}
//###必须包含上面的语句,否则可能不能恢复(三步攻克)-------------------------
Tuser admin = new Tuser();//高级管理员初始化
admin.setId("0");
admin.setName("admin");
admin.setPwd(MD5Util.encode("admin"));
userDao.saveOrUpdate(admin);
}
/**
* 修复左边菜单
*/
private void repairMenu() {
Tmenu root = new Tmenu();
//修复时,Id不能用随机码,必须是固定的,否则action执行多次,会插入多条数据
root.setId("0");
root.setText("首页");
root.setIconcls(null);
root.setUrl(null);
menuDao.saveOrUpdate(root);
Tmenu sysManag = new Tmenu();
sysManag.setId("xtgl");
sysManag.setTmenu(root);
sysManag.setText("系统管理");
sysManag.setUrl("");
menuDao.saveOrUpdate(sysManag);
Tmenu userManag = new Tmenu();
userManag.setId("yhgl");
userManag.setTmenu(sysManag);
userManag.setText("用户管理");
userManag.setUrl("/admin/userManag.jsp");
menuDao.saveOrUpdate(userManag);
Tmenu roleManag = new Tmenu();
roleManag.setId("jsgl");
roleManag.setTmenu(sysManag);
roleManag.setText("角色管理");
roleManag.setUrl("");
menuDao.saveOrUpdate(roleManag);
Tmenu PermManag = new Tmenu();
PermManag.setId("qxgl");
PermManag.setTmenu(sysManag);
PermManag.setText("权限管理");
PermManag.setUrl("");
menuDao.saveOrUpdate(PermManag);
Tmenu menuManag = new Tmenu();
menuManag.setId("cdgl");
menuManag.setTmenu(sysManag);
menuManag.setText("菜单管理");
menuManag.setUrl("");
menuDao.saveOrUpdate(menuManag);
Tmenu bugManag = new Tmenu();
bugManag.setId("buggl");
bugManag.setTmenu(sysManag);
bugManag.setText("用户管理管理");
bugManag.setUrl("");
menuDao.saveOrUpdate(bugManag);
}
}
4. Action
4.1 BaseAction.java
@ParentPackage("basePackage")
@Namespace("/")
public class BaseAction {
public void writeJson(Object object){
try{
String json = JSON.toJSONStringWithDateFormat(object, "yyyy-MM-dd HH:mm:ss");
ServletActionContext.getResponse().setContentType("text/html;charset=utf-8");
ServletActionContext.getResponse().getWriter().write(json);
ServletActionContext.getResponse().getWriter().flush();
ServletActionContext.getResponse().getWriter().close();
}catch(IOException e){
e.printStackTrace();
}
}
}
4.2 UserAction.java
//不把action配置在struts.xml中,直接在action类中写注解
//相当于在<package name="basePackage" extends="struts-default"></package>中配置UserAction
@Namespace("/")
// 直接在根目录下访问,如果UserAction在/demo下则是"/demo"
// Action的整个类标识,调用时使用动态方法进行调用(用叹号)。如果用方法标识,则直接配置在方法名上面,如下面注释
@Action(value = "userAction")
public class UserAction extends BaseAction implements ModelDriven<User> {// 注意这里不是Tuser
private static final Logger logger = Logger.getLogger(UserAction.class);
User user = new User();
private UserService userService;
public UserService getUserService() {
return userService;
}
@Autowired
// 表示自动注入
public void setUserService(UserService userService) {
this.userService = userService;
}
// @Action(value="userAction")
// 相当于配置文件形式:<action name="userTestAction" method="test" class="cn.hw.UserAction"/>
public void test() {
logger.info("进入Action_test");
userService.test();
}
// public void addUser() {
// Tuser t = new Tuser();
// t.setCreatTime(new Date());
// t.setId(UUID.randomUUID().toString());
// t.setName("xxx");
// t.setPwd("1111222");
// }
/**
* 虽然是void,但是这个方法是有返回值的,只是在里面通过其它方法writeJson()将json数据返回到了前台
*/
public void reg() {
// Map<String,Object> m = new HashMap<String,Object>();//1
HwJson j = new HwJson();
try {
// ▲注意点:如果add()的参数有100项,则这种方式不好,则应该直接传对象,
userService.save(user);
// m.put("success", true);//1
// m.put("msg", "注册成功");//1
j.setSuccess(true);
j.setMsg("注册成功");
} catch (Exception e) {
// m.put("success",false);//1
// m.put("msg", e.getMessage());//1
j.setMsg(e.getMessage());
}
super.writeJson(j);// 调用父类的方法
}
public User getModel() {
return this.user;
}
public void login() {
User u = userService.login(user);
HwJson j = new HwJson();
if (u != null) {
j.setSuccess(true);
j.setMsg("登录成功");
} else {
j.setMsg("登录失败,用户名或密码错误");
}
super.writeJson(j);
}
public void datagrid() {
// 依据EasyUI框架需要的json数据内容定义的pageModel
// 也可以用Map
// Map m = new HashMap();
// m.put("total",0);
// m.put("rows",new ArrayList());
super.writeJson(userService.datagrid(user));
}
/**
* 添加一条数据
*/
public void addUser() {
HwJson j = new HwJson();
try {
userService.save(user);
j.setSuccess(true);
j.setMsg("添加成功");
j.setObj(user);
} catch (Exception e) {
j.setMsg(e.getMessage());
}
super.writeJson(j);
}
public void remove() {
userService.remove(user.getIds());
}
public void edit() {
HwJson j = new HwJson();
try{
User u = userService.edit(user);
j.setSuccess(true);
j.setMsg("编辑成功");
j.setObj(u);
}catch(Exception e){
j.setMsg(e.getMessage());
}
super.writeJson(j);
}
}
5. Utils
5.1 MD5Util.java
注意:引入的包不同,所加密的最后结果也将不同,所适用的场合也将不同。
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;
public class MD5Util {
public static String encode(String message){
try {
MessageDigest md=MessageDigest.getInstance("md5");
byte b[] = md.digest(message.getBytes());
return new BASE64Encoder().encode(b);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
5.2 RepairListener:用于测试时修复数据的监听器
public class RepairListener implements ServletContextListener, ServletContextAttributeListener,
HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener,
HttpSessionBindingListener, ServletRequestListener, ServletRequestAttributeListener {
private static final Logger logger = Logger.getLogger(RepairListener.class);
private static ApplicationContext ctx = null;
public RepairListener() {
}
//其它方法略
public void contextInitialized(ServletContextEvent evt) {
logger.info("修复数据库");
ctx = WebApplicationContextUtils.getWebApplicationContext(evt.getServletContext());
RepairService repairService = (RepairService) ctx.getBean("repairService");
repairService.repair();
}
}