SSH物流开发系统设计:搭建框架并实现登录
2017-06-08 17:35
761 查看
一、搭建项目基本框架
1、创建一个动态web项目(Dynamic Web project)2、导入相关jar包(SSH、spring依赖、日志、数据库驱动,shiro支持)
3、配置web.xml(struts2的过滤器、spring监听器、解决Hibernate延迟加载问题的过滤器、解决中文乱码的过滤器)
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>bos19</display-name> <filter> <!-- 权限验证框架 --> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <!-- 解决乱码问题 --> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 解决Hibernate延时加载的问题 --> <filter> <filter-name>openSession</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSession</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring监听器 --> <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> <!-- struts2过滤器 --> <filter> <filter-name>strust2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>strust2</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <!-- 配置服务器内部转发经过struts2过滤器处理 --> <dispatcher>FORWARD</dispatcher> </filter-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>
4、创建项目目录结构
如下图:
com.crm.bos.utils:存放项目中的工具类。
com.crm.bos.domain:存放的是实体类即相关pojo类以及Hibernate映射文件。
com.crm.bos.dao:存放Hibernate的Dao层设计类。
com.crm.bos.service:存放service层代码。
com.crm.bos.web:存放web控制层的代码,例如struts2的action类和拦截器类等。
com.crm.bos.shiro:存放关于shiro框架的相关代码。
5、在config目录中提供struts2的配置文件
<?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> <constant name="struts.devMode" value="true" /> <constant name="struts.objectFactory" value="spring"/> <package name="basicstruts2" extends="struts-default"> <!-- 需要进行权限控制的页面访问 --> <action name="page_*_*"> <result name="success" type="dispatcher">/WEB-INF/pages/{1}/{2}.jsp</result> </action> </package> </struts>
6、在config目录下提供spring的配置文件applicationContext.xml
<!-- 加载jdbc属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${driverClass}"/> <property name="jdbcUrl" value="${jdbcUrl}"/> <property name="user" value="${user}"/> <property name="password" value="${password}"/> </bean> <!-- spring框架用于整合Hibernate的工厂bean --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 注入Hibernate相关的属性 --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <!-- 注入Hibernate的映射文件 --> <property name="mappingDirectoryLocations"> <list> <value>classpath:com/crm/bos/domain</value> </list> </property> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 组件扫描 --> <context:component-scan base-package="com.crm.bos"/> <!-- 引入注解解析器 --> <context:annotation-config/> <!-- 事务注解 --> <tx:annotation-driven />
7、提供项目所需的前端资源文件。
二、建立持久层基本框架
这里的持久层设计基于泛型和反射,我们在编写 Dao 层的时候,总会遇到通用的增删改查方法,每一次都要写声明和实现是一件很繁琐的事情,而且代码有很多事相同点。于是使用面向对象的三大特性和泛型语法来简化持久层的开发。基本关系如下图:
首先设计IBaseDao接口
/** * 抽取持久层通用方法 * * @param <T> */ public interface IBaseDao<T> { public void save(T entity); public void delete(T entity); public void update(T entity); public void saveOrUpdate(T entity); public T findById(Serializable id); public List<T> findAll(); //提供通用修改方法 public void executeUpdate(String queryName,Object ...objects); public void pageQuery(PageBean pageBean); public List<T> findByCriteria(DetachedCriteria detachedCriteria); }
设计接口实现类BaseDaoImpl
/** * 持久层通用实现 * */ public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> { // 实体类型 private Class<T> entityClass; // 使用注解方式进行依赖注入 @Resource // @Autowired // @Qualifier(value="abc") public void setMySessionFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); } /** * 在构造方法中动态获得操作的实体类型 */ public BaseDaoImpl() { // 获得父类(BaseDaoImpl<T>)类型 ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获得父类上的泛型数组 Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments(); entityClass = (Class<T>) actualTypeArguments[0]; } public void save(T entity) { this.getHibernateTemplate().save(entity); } public void delete(T entity) { this.getHibernateTemplate().delete(entity); } public void update(T entity) { this.getHibernateTemplate().update(entity); } public T findById(Serializable id) { return this.getHibernateTemplate().get(entityClass, id); } public List<T> findAll() {// FROM User String hql = "FROM " + entityClass.getSimpleName(); return this.getHibernateTemplate().find(hql); } /** * 通用更新方法 */ public void executeUpdate(String queryName, Object... objects) { Session session = this.getSession();// 从本地线程中获得session对象 // 使用命名查询语句获得一个查询对象 Query query = session.getNamedQuery(queryName); // 为HQL语句中的?赋值 int i = 0; for (Object arg : objects) { query.setParameter(i++, arg); } query.executeUpdate();// 执行更新 } /** * 通用分页查询方法 */ public void pageQuery(PageBean pageBean) { int currentPage = pageBean.getCurrentPage(); int pageSize = pageBean.getPageSize(); DetachedCriteria detachedCriteria = pageBean.getDetachedCriteria(); //总数据量----select count(*) from bc_staff //改变Hibernate框架发出的sql形式 detachedCriteria.setProjection(Projections.rowCount());//select count(*) from bc_staff List<Long> list = this.getHibernateTemplate().findByCriteria(detachedCriteria); Long total = list.get(0); pageBean.setTotal(total.intValue());//设置总数据量 detachedCriteria.setProjection(null);//修改sql的形式为select * from .... //重置表和类的映射关系 detachedCriteria.setResultTransformer(DetachedCriteria.ROOT_ENTITY); //当前页展示的数据集合 int firstResult = (currentPage - 1) * pageSize; int maxResults = pageSize; List rows = this.getHibernateTemplate().findByCriteria(detachedCriteria, firstResult, maxResults); pageBean.setRows(rows); } public void saveOrUpdate(T entity) { this.getHibernateTemplate().saveOrUpdate(entity); } public List<T> findByCriteria(DetachedCriteria detachedCriteria) { return this.getHibernateTemplate().findByCriteria(detachedCriteria); } }
通过如下代码将Spring配置文件中的配置的sessionFactory注入到该set方法中,其名字对应的是set方法的输入参数与set方法名无关。
@Resource public void setMySessionFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); }
这里通过在构造方法中动态获得运行时类的信息来实现泛型的应用。
三、表现层设计
这里也提取出一个基础action类以供其他action继承。其基本关系如下:
具体代码如下:
public class BaseAction<T> extends ActionSupport implements ModelDriven<T> { @Resource protected IUserService userService; @Autowired protected IStaffService staffService; @Autowired protected IRegionService regionService; @Autowired protected ISubareaService subareaService; @Autowired protected IDecidedzoneService decidedzoneService; @Autowired protected INoticebillService noticebillService; @Autowired protected IWorkordermanageService workordermanageService; @Autowired protected IFunctionService functionService; @Autowired protected IRoleService roleService; protected T model;// 模型对象 protected PageBean pageBean = new PageBean(); DetachedCriteria detachedCriteria = null; protected int page;// 分页参数 protected int rows; public T getModel() { return model; } public void setPage(int page) { pageBean.setCurrentPage(page); } public void setRows(int rows) { pageBean.setPageSize(rows); } // 模型对象类型在构造方法中动态获得 public BaseAction() { ParameterizedType genericSuperclass = null; Type genericSuperclass2 = this.getClass().getGenericSuperclass(); if(genericSuperclass2 instanceof ParameterizedType){ genericSuperclass=(ParameterizedType) genericSuperclass2; }else {//此时this为shiro的代理对象 genericSuperclass=(ParameterizedType) this.getClass().getSuperclass().getGenericSuperclass(); } Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments(); Class<T> entityClass = (Class<T>) actualTypeArguments[0]; detachedCriteria = DetachedCriteria.forClass(entityClass); pageBean.setDetachedCriteria(detachedCriteria); try { model = entityClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } // 将pageBean对象转为json public void writePageBean2Json(PageBean pageBean, String[] excludes) { JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(excludes); JSONObject jsonObject = JSONObject.fromObject(pageBean, jsonConfig); String json = jsonObject.toString(); ServletActionContext.getResponse().setContentType( "text/json;charset=UTF-8"); try { ServletActionContext.getResponse().getWriter().print(json); } catch (IOException e) { e.printStackTrace(); } } // 将list集合转为json public void writeList2Json(List list, String[] excludes) throws IOException { JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(excludes); JSONArray jsonObject = JSONArray.fromObject(list, jsonConfig); String json = jsonObject.toString(); ServletActionContext.getResponse().setContentType( "text/json;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(json); } //将普通对象转为json public void writeObject2Json(Object object, String[] excludes) throws IOException { JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(excludes); JSONObject jsonObject = JSONObject.fromObject(object, jsonConfig); String json = jsonObject.toString(); ServletActionContext.getResponse().setContentType( "text/json;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(json); }
这里将所有的service对象都注入进来,这样就可以统一进行service的管理和应用。在构造方法中利用反射机制来创建模型对象。
四、基于baseDao和BaseAction实现用户登录
1、前端页面和基础pojo类前端展示页面如下:
<div class="loginForm"> <form id="loginform" name="loginform" method="post" class="niceform" action="${pageContext.request.contextPath }/userAction_login.action"> <div id="idInputLine" class="loginFormIpt showPlaceholder" style="margin-top: 5px;"> <input id="loginform:idInput" type="text" name="username" class="loginFormTdIpt" maxlength="50" /> <label for="idInput" class="placeholder" id="idPlaceholder">帐号:</label> </div> <div class="forgetPwdLine"></div> <div id="pwdInputLine" class="loginFormIpt showPlaceholder"> <input id="loginform:pwdInput" class="loginFormTdIpt" type="password" name="password" value="" /> <label for="pwdInput" class="placeholder" id="pwdPlaceholder">密码:</label> </div> <div class="loginFormIpt loginFormIptWiotTh" style="margin-top:58px;"> <div id="codeInputLine" class="loginFormIpt showPlaceholder" style="margin-left:0px;margin-top:-40px;width:50px;"> <input id="loginform:codeInput" class="loginFormTdIpt" type="text" name="checkcode" title="请输入验证码" /> <img id="loginform:vCode" src="${pageContext.request.contextPath }/validatecode.jsp" onclick="javascript:document.getElementById('loginform:vCode').src='${pageContext.request.contextPath }/validatecode.jsp?'+Math.random();" /> </div> <a href="#" onclick="document.forms[0].submit();" id="loginform:j_id19" name="loginform:j_id19"> <span id="loginform:loginBtn" class="btn btn-login" style="margin-top:-36px;">登录</span> </a> </div> <div> <font color="red"> <s:actionerror/> </font> </div> </form> </div>
pojo类如下:User
/** * User entity. @author MyEclipse Persistence Tools */ public class User implements java.io.Serializable { // Fields private String id; private String username; private String password; private Double salary; private Date birthday; private String gender;// 1表示男,2表示女 private String station; private String telephone; private String remark; private Set<Noticebill> noticebills = new HashSet<Noticebill>(); private Set<Role> roles = new HashSet<Role>(); public String getFormateBirthday() { if (birthday != null) { return new SimpleDateFormat("yyyy-MM-dd").format(birthday); } else { return "未提交生日"; } } public String getRoleNames() { String names = ""; if (roles != null && roles.size() > 0) { for (Role role : roles) { names += role.getName() + " "; } } return names; } // Constructors /** default constructor */ public User() { } /** minimal constructor */ public User(String id, String username, String password) { this.id = id; this.username = username; this.password = password; } /** full constructor */ public User(String id, String username, String password, Double salary, Date birthday, String gender, String station, String telephone, String remark) { this.id = id; this.username = username; this.password = password; this.salary = salary; this.birthday = birthday; this.gender = gender; this.station = station; this.telephone = telephone; this.remark = remark; } // Property accessors public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Double getSalary() { return this.salary; } public void setSalary(Double salary) { this.salary = salary; } public Date getBirthday() { return this.birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getGender() { return this.gender; } public void setGender(String gender) { this.gender = gender; } public String getStation() { return this.station; } public void setStation(String station) { this.station = station; } public String getTelephone() { return this.telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getRemark() { return this.remark; } public void setRemark(String remark) { this.remark = remark; } public Set<Noticebill> getNoticebills() { return noticebills; } public void setNoticebills(Set<Noticebill> noticebills) { this.noticebills = noticebills; } public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } }
对应的Hibernate映射文件如下:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.crm.bos.domain.User" table="t_user"> <id name="id" type="java.lang.String"> <column name="id" length="32" /> <generator class="uuid" /> </id> <property name="username" type="java.lang.String"> <column name="username" length="20" not-null="true" /> </property> <property name="password" type="java.lang.String"> <column name="password" length="32" not-null="true" /> </property> <property name="salary" type="java.lang.Double"> <column name="salary" precision="22" scale="0" /> </property> <property name="birthday" type="java.util.Date"> <column name="birthday" length="0" /> </property> <property name="gender" type="java.lang.String"> <column name="gender" length="10" /> </property> <property name="station" type="java.lang.String"> <column name="station" length="40" /> </property> <property name="telephone" type="java.lang.String"> <column name="telephone" length="11" /> </property> <property name="remark" type="java.lang.String"> <column name="remark" /> </property> <set name="noticebills" inverse="true"> <key> <column name="user_id" length="32" /> </key> <one-to-many class="com.crm.bos.domain.Noticebill" /> </set> <set name="roles" table="user_role" catalog="bos19"> <key> <column name="user_id" length="32" not-null="true" /> </key> <many-to-many entity-name="com.crm.bos.domain.Role"> <column name="role_id" length="32" not-null="true" /> </many-to-many> </set> </class> <!-- 命名查询语句 --> <query name="editPassword"> UPDATE User SET password = ? WHERE id = ? </query> </hibernate-mapping>
2、在UserAction中提供login方法
@Resource private IUserService userService; //通过属性驱动接收验证码 private String checkcode; public void setCheckcode(String checkcode) { this.checkcode = checkcode; } public String login(){ //生成的验证码 String key = (String) ServletActionContext.getRequest().getSession().getAttribute("key"); //判断用户输入的验证码是否正确 if(StringUtils.isNotBlank(checkcode) && checkcode.equals(key)){ //验证码正确 User user = userService.login(model); if(user != null){ //登录成功,将User放入session域,跳转到系统首页 ServletActionContext.getRequest().getSession().setAttribute("loginUser", user); return "home"; }else{ //登录失败,设置错误提示信息,跳转到登录页面 this.addActionError(this.getText("loginError")); return "login"; } }else{ //验证码错误,设置错误提示信息,跳转到登录页面 this.addActionError(this.getText("validateCodeError")); return "login"; } }
3、提供UserService类
@Service @Transactional public class UserServiceImpl implements IUserService{ //注入dao @Autowired private IUserDao userDao; public User login(User user) { String username = user.getUsername(); String password = user.getPassword();//明文 password = MD5Utils.md5(password);//md5加密 return userDao.findByUsernameAndPassword(username,password); } }
4、在UserDao中扩展方法,根据用户名和密码查询用户
/** * 根据用户名和密码查询用户 */ public User findByUsernameAndPassword(String username, String password) { String hql = "FROM User u WHERE u.username = ? AND u.password = ?"; List<User> list = this.getHibernateTemplate().find(hql, username,password); if(list != null && list.size() > 0){ return list.get(0); } return null; }
5、在struts.xml中注册国际化文件
<!-- 注册国际化文件 --> <constant name="struts.custom.i18n.resources" value="message"></constant>
6、在login.jsp页面中使用struts2提供的标签展示错误提示信息
<div> <font color="red"> <s:actionerror/> </font> </div>
7、自定义拦截器完成登录验证
拦截器定义如下:
public class BOSLoginInterceptor extends MethodFilterInterceptor { // 拦截方法 protected String doIntercept(ActionInvocation invocation) throws Exception { User user = (User) ServletActionContext.getRequest().getSession() .getAttribute("loginUser"); if(user == null){ //未登录,跳转到登录页面 return "login"; } return invocation.invoke();// 放行 } }
在struts配置文件中拦截器配置如下:
<package name="basicstruts2" extends="struts-default"> <!-- 定义拦截器 --> <interceptors> <interceptor name="BosLoginInterceptor" class="com.crm.bos.web.interceptor.BosLoginInterceptor"> <!-- 不拦截登录连接 --> <param name="excludeMethods">login</param> </interceptor> <!-- 自定义拦截器栈 --> <interceptor-stack name="myStack"> <interceptor-ref name="BosLoginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 指定默认拦截器栈 --> <default-interceptor-ref name="myStack"></default-interceptor-ref> <global-results> <result name="login">/login.jsp</result> </global-results> <!-- 需要进行权限控制的页面访问 --> <action name="page_*_*"> <result name="success" type="dispatcher">/WEB-INF/pages/{1}/{2}.jsp </result> </action>
8、基于ajax实现修改密码
第一步:为密码输入框进行输入校验,使用easyUI提供的easyui-validatebox。
<table cellpadding=3> <tr> <td>新密码:</td> <td><input id="txtNewPass" type="Password" class="txt01 easyui-validatebox" required="true" data-options="validType:'length[4,8]'" /></td> </tr> <tr> <td>确认密码:</td> <td><input id="txtRePass" type="Password" class="txt01 easyui-validatebox" required="true" data-options="validType:'length[4,8]'" /></td> </tr> </table>
第二步:为“确定”按钮绑定事件
<script type="text/javascript"> //为“确定”按钮绑定事件 $("#btnEp").click(function(){ //进行表单校验 var v = $("#editPasswordForm").form("validate");//对应表单中的所有输入框进行校验 if(v){//表单校验通过 //判断两次输入是否一致 var v1 = $("#txtNewPass").val(); var v2 = $("#txtRePass").val(); if(v1 == v2){ //输入一致,发送ajax请求,修改当前用户的密码 var url = "${pageContext.request.contextPath}/userAction_editPassword.action"; $.post(url,{"password":v1},function(data){ if(data == '1'){ //修改密码成功 $.messager.alert("提示信息","密码修改成功!","info"); }else{ //修改失败 $.messager.alert("提示信息","密码修改失败!","warning"); } //关闭修改密码的窗口 $("#editPwdWindow").window("close"); }); }else{ //输入不一致,提示用户输入不一致 $.messager.alert("提示信息","两次输入密码不一致!","warning"); } } }); </script>
第三步:在UserAction中提供editPassword方法,修改密码
/** * 修改当前登录用户密码 * @throws IOException */ public String editPassword() throws IOException{ User user = (User) ServletActionContext.getRequest().getSession().getAttribute("loginUser"); String password = model.getPassword();//新密码 password = MD5Utils.md5(password); String flag = "1"; try{ userService.editPassword(password,user.getId()); }catch (Exception e) { //修改密码失败 flag = "0"; } ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(flag); return NONE; }
第四步:在BaseDao中扩展一个通用的更新方法
/** * 通用更新方法 */ public void executeUpdate(String queryName, Object... objects) { Session session = this.getSession();// 从本地线程中获得session对象 // 使用命名查询语句获得一个查询对象 Query query = session.getNamedQuery(queryName); // 为HQL语句中的?赋值 int i = 0; for (Object arg : objects) { query.setParameter(i++, arg); } query.executeUpdate();// 执行更新 }
第五步:在User.hbm.xml中定义一个HQL语句,用于修改密码
<!-- 命名查询语句 --> <query name="editPassword"> UPDATE User SET password = ? WHERE id = ? </query>
五、源码点我
相关文章推荐
- SSH物流开发系统设计:权限认证实现
- SSH物流开发系统设计:业务受理逻辑实现
- Winform开发框架之系统重新登录、自动登录实现
- 【原创】SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能
- c# 登录界面设计与框架基础搭建雏形--(学生管理系统)
- NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
- SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能
- Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现
- [置顶] Win10下用IDEA搭建Struts2+Spring4+Hibernate5(SSH)框架,实现用户登录注册
- NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
- Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解 (3) - 实现最基本的登录处理
- SSH物流开发系统设计:区域和分区的增删改查
- 搭建开发框架Express,实现Web网站登录验证
- Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解 (3) - 实现最基本的登录处理
- 搭建开发框架Express,实现Web网站登录验证
- Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解 (3) - 实现最基本的登录处理
- NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
- SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能
- 搭建开发框架Express,实现Web网站登录验证
- SSH物流开发系统设计:定区的相关操作和设计