• Spring MVC学习笔记——完整的用户登录


    工程地址:https://github.com/tonglin0325/article-manager.git

    1.搭建环境的第一步是导包,把下面这些包都导入工程中

    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/aop
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/apache-commons-logging
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/apache-log4j
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/bean-validator
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/dbcp
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/hibernate-3.6.8.
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/JSTL
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/mysql
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/pager
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/sitemesh
    /media/common/工作/Ubuntu软件/SpringMVC_jar包整理/spring

    手动导包也可以,不过不是很方便,推荐学习使用maven的pom.xml文件来导入jar包

    整个系统的结构

    表示层(JSP页面),一般包名是view

        ▼

    控制层,一般包名是action或者web,控制层也会操作实体层

      

    业务逻辑层,一般包名是service

      

    数据持久层,一般包名是dao

      

    实体层(JavaBean),一般包名是model或者entity

    写成的过程和上面的方向相反从下往上写

    实体Entity层

      1.先写User类

        Id,username,nickname,password,email

        其中还包括注入

      2.再写Page类

        public class Pager<T>

        List<T> datas、offset、size、total

      3.写SystemContext类

      7.写UserException异常类

    数据持久层dao层,主要是操作Hibernate,还要写beans.xml

      4.写IUserDao接口

        增、更新、删除、根据ID查用户load、查所用用户List<User> list、查分页Pager<User> find、根据username查用户loadByUsername

      5.实现IUserDao接口

        分页find()中取得SystemContext类

    业务逻辑层service层,主要是写验证

      6.写IUserService接口

        增、更新、删除、根据ID查用户load、查所用用户List<User> list、查分页Pager<User> find、根据username查用户loadByUsername

      8.实现IUserService接口

        密码登录验证login、添加用户、修改用户、删除用户、查询用户、列出所有用户、分页find()

    控制层action层

      9.LoginFilter.java登录权限,实现Filter接口,doFilter()方法

        在请求是/user/*的时候拦截验证权限,没有权限重定向/login,有权限放行

      10.SystemContext.java分页过滤,实现Filter接口,doFilter()方法

        在请求是/*中,如果参数为Pager.offset的时候,拦截取得offset,设置SystemContext中的offset和size

      11.IndexController.java,Session共享数据

        在请求是/login的时候,将ModelMap中的属性放入Session中,实现多窗口共享数据

      12.UserController.java,总的请求为/user,这也就是MVC模型中的RequestMapping

        在请求是/user和/的时候,向model模型中添加——userService.find()

        在请求是/add的时候(分GET和POST),向model模型中添加——new User()

        在请求是/{id}的时候,向model模型中添加——userService.load(id)

        在请求是/{id}/update的时候(分GET和POST)...

        在请求是/{id}/delete的时候...

        最后再传给DispatchServlet,使用model从Controller给视图传值

        在jsp中通过 ${ } 取得属性

        记得加上@Controller,通过Annotation来配置控制器

    注意:在持久层、业务层、控制层中,分别采用@Repository、@Service、@Controller对分层中的类进行注释

    2.在工程的src/目录下加入beans.xml、jdbc.properties和log4j.properties这三个文件

    3.新建一个数据库文件

      新建一个数据库spring_user

    mysql> create database spring_user;
    

     

      并把字符编码改成UTF-8,可以参考 Ubuntu下的MySQL安装


     
       添加spring_user数据库
    create database spring_user default character set utf8 collate utf8_general_ci;
    
     

       添加t_user表

    CREATE TABLE IF NOT EXISTS `t_user` (`username` varchar(64) NOT NULL,`password` varchar(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

     

      插入用户和密码

    INSERT INTO t_user (username,password) VALUES('admin','admin');
    

     4.接下来在页面就可以用admin来登录

      而且中文也正常显示

     

    整个项目的结构

      1.JSP页面:登录、添加、列表、详情、更新、错误

      2.实体层(Bean或者model):分页类、分页查询结果类、用户类、Exception类

      3.控制层(Action):页面控制器、登录过滤器、分页查询结果过滤器、用户控制器

      4.业务逻辑层(Service):一个接口和一个实现类(包括注入userDAO、登入验证、添删该查用户等等)

      5.数据持久层(DAO):一个接口和一个实现类(和HibernateDaoSupport相关,用户增删改查等等)

    1.JSP页面

      login.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>用户登录</title>
    </head>
    <body>
    <form method="post">
    	用户名:<input type="text" name="username"/><br/>
    	用户密码:<input type="password" name="password"/><br/>
    	<input type="submit" value="用户登录"/>
    </form>
    </body>
    </html>
    

      error.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>发现异常</title>
    </head>
    <body>
    <h1>${exception.message }</h1>
    </body>
    </html>
    

     

     add.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>用户添加</title>
    </head>
    <body>
    <sf:form method="post" modelAttribute="user">
    <table width="700" align="center" border="1">
    	<tr>
    	<td>用户名:</td><td><sf:input path="username"/><sf:errors path="username"/></td>
    	</tr>
    	<tr>
    	<td>用户密码:</td><td><sf:password path="password"/><sf:errors path="password"/></td>
    	</tr>
    	<tr>
    	<td>用户昵称:</td><td><sf:input path="nickname"/></td>
    	</tr>
    	<tr>
    	<td>用户邮箱:</td><td><sf:input path="email"/><sf:errors path="email"/></td>
    	</tr>
    	<tr>
    	<td colspan="2">
    		<input type="submit" value="用户添加"/>
    	</td>
    	</tr>
    </table>
    </sf:form>
    </body>
    </html>
    

      list.jsp 

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>用户列表</title>
    </head>
    <body>
    <table width="700" align="center" border="1">
    	<tr>
    	<td>用户标识:${pagers.total }</td><td>用户名</td><td>用户昵称</td><td>用户密码</td><td>用户邮箱</td>
    	<td>操作</td>
    	</tr>
    	<c:if test="${pagers.total le 0 }">
    		<tr>
    		<td colspan="6">目前还没有用户数据</td>
    		</tr>
    	</c:if>
    	<c:if test="${pagers.total gt 0}">
    		<c:forEach items="${pagers.datas }" var="u">
    		<tr>
    		<td>${u.id }</td><td>${u.username }</td>
    		<td><a href="${u.id }">${u.nickname }</a></td>
    		<td>${u.password }</td><td>${u.email }</td>
    		<td><a href="${u.id }/update">更新</a> <a href="${u.id }/delete">删除</a></td>
    		</tr>
    		</c:forEach>
    		<tr>
    		<td colspan="6">
    			<jsp:include page="/inc/pager.jsp">
    				<jsp:param value="users" name="url"/>
    				<jsp:param value="${pagers.total}" name="items"/>
    			</jsp:include>
    		</td>
    		</tr>	
    	</c:if>
    </table>
    </body>
    </html>
    

     

       show.jsp 

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    		<title>用户[${user.nickname }]详细信息</title>
    	</head>
    	
    	<body>
    		<table width="700" align="center" border="1">
    			<tr>
    				<td>用户标识:</td><td>${user.id }</td>
    			</tr>
    			<tr>
    				<td>用户名:</td><td>${user.username }</td>
    			</tr>
    			<tr>
    				<td>用户密码:</td><td>${user.password }</td>
    			</tr>
    			<tr>
    				<td>用户昵称:</td><td>${user.nickname }</td>
    			</tr>
    			<tr>
    				<td>用户邮箱:</td><td>${user.email }</td>
    			</tr>
    		</table>
    	</body>
    </html>
    

      update.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    		<title>用户更新</title>
    	</head>
    	<body>
    		<sf:form method="post" modelAttribute="user">
    			<table width="700" align="center" border="1">
    				<tr>
    					<td>用户名:</td><td>${user.username }<sf:hidden path="username"/></td>
    				</tr>
    				<tr>
    					<td>用户密码:</td><td><sf:password path="password"/><sf:errors path="password"/></td>
    				</tr>
    				<tr>
    					<td>用户昵称:</td><td><sf:input path="nickname"/></td>
    				</tr>
    				<tr>
    					<td>用户邮箱:</td><td><sf:input path="email"/><sf:errors path="email"/></td>
    				</tr>
    				<tr>
    					<td colspan="2">
    						<input type="submit" value="用户更新"/>
    					</td>
    				</tr>
    			</table>
    		</sf:form>
    	</body>
    </html>
    

    分页结构

    5.在src/目录下建立包org.common.model

       model包中一般放的是实体类,这些类定义了一些基本的属性以及简单的get/set方法,这些类和数据库中的表存在对应关系

      一般都是javabean对象,例如与数据库的某个表相关联。

      

       先写User类,文件名字为User.java,其中就是简单的get方法和set方法

    package org.common.model;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity											//如果我们当前这个bean要设置成实体对象,就需要加上Entity这个注解
    @Table(name="t_user")			//设置数据库的表名
    public class User {
    	private int id;
    	private String username;
    	private String nickname;
    	private String password;
    	private String email;
    	
    	//(建议不要在属性上引入注解,因为属性是private的,如果引入注解会破坏其封装特性,所以建议在getter方法上加入注解)
    	@Id											//定义为数据库的主键ID  
    	@GeneratedValue				//ID的生成策略为自动生成
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getNickname() {
    		return nickname;
    	}
    	public void setNickname(String nickname) {
    		this.nickname = nickname;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	public String getEmail() {
    		return email;
    	}
    	public void setEmail(String email) {
    		this.email = email;
    	}
    	
    }
    

       接下来只需要在hibernate.cfg.xml文件里面将该实体类加进去即可:

    <!-- 基于annotation的配置 -->
            <mapping class="com.xiaoluo.bean.User"/>
    <!-- 基于hbm.xml配置文件 -->
            <mapping resource="com/xiaoluo/bean/User.hbm.xml"/>
    

      但是,我们采取的方法是使用Spring配置数据源,即在Spring容器中定义数据源,指定映射文件、设置hibernate控制属性等信息,完成集成组装的工作,完全抛开hibernate.cfg.xml配置文件,具体的方法就是在beans.xml文件中加入

    其中的Spring注解hibernate实体方法

    <property name="annotatedClasses">
                <list>
                    <value>com.sise.domain.Admin</value>
                    <value>com.sise.domain.Remind</value>
                    <value>com.sise.domain.User</value>
                </list>
    </property>
    

     可以使用下面的来替代

    <!-- 设置Spring取那个包中查找相应的实体类,指定hibernate实体类映射文件 -->
    		<property name="packagesToScan">
    			<value>org.common.model</value>
    		</property>
    
    	<!-- 导入Src目录下的jdbc.properties文件 -->
    	<context:property-placeholder location="classpath:jdbc.properties" />
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    		destroy-method="close">
    		<property name="driverClassName" value="${jdbc.driverClassName}" />
    		<property name="url" value="${jdbc.url}" />
    		<property name="username" value="${jdbc.username}" />
    		<property name="password" value="${jdbc.password}" />
    		<!-- 配置连接池的初始值 -->
    		<property name="initialSize" value="1" />
    		<!-- 连接池的最大值 -->
    		<!-- <property name="maxActive" value="500"/> -->
    		<!-- 最大空闲时,当经过一个高峰之后,连接池可以将一些用不到的连接释放,一直减少到maxIdle为止 -->
    		<!-- <property name="maxIdle" value="2"/> -->
    		<!-- 当最小空闲时,当连接少于minIdle时会自动去申请一些连接 -->
    		<property name="minIdle" value="1" />
    		<property name="maxActive" value="100" />
    		<property name="maxIdle" value="20" />
    		<property name="maxWait" value="1000" />
    	</bean>
    	
    	<!--创建Spring的SessionFactory工厂 -->
    	<!-- 如果使用的是Annotation的方式,不能使用LocalSessionFactoryBean,而应该使用 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean -->
    	<bean id="sessionFactory"
    		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    		
    		<!-- 注入数据源 -->
    		<property name="dataSource" ref="dataSource" />
    		
    		<!-- 设置Spring取那个包中查找相应的实体类,指定hibernate实体类映射文件 -->
    		<property name="packagesToScan">
    			<value>org.common.model</value>
    		</property>
    		
    		<!-- 指定hibernate配置属性-->
    		<property name="hibernateProperties">
    			<!-- <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> -->
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    				<prop key="hibernate.show_sql">true</prop>
    				<prop key="hibernate.hbm2ddl.auto">update</prop>
    				<prop key="hibernate.format_sql">false</prop>
    			</props>
    		</property>
    	</bean>
    

    6.在src/目录下建立包org.common.dao

      在dao中,写与数据库的操作,增删改查等方法

      首先写IUserDao接口,文件名为IUserDao.java

    package org.common.dao;
    
    import java.util.List;
    
    import org.common.model.Pager;
    import org.common.model.User;
    
    public interface IUserDao {			//IUserDao接口
    	public void add(User user);
    	public void update(User user);
    	public void delete(int id);
    	public User load(int id);
    	public List<User> list();
    	public Pager<User> find();
    	public User loadByUsername(String username);
    }
    

       同时,还要在包org.common.model下加上分页的类,文件名是Page.java

    package org.common.model;
    
    import java.util.List;
    
    public class Pager<T> {		//分页
    	private List<T> datas;
    	private int offset;
    	private int size;
    	private long total;
    	
    	public List<T> getDatas() {
    		return datas;
    	}
    	public void setDatas(List<T> datas) {
    		this.datas = datas;
    	}
    	public int getOffset() {
    		return offset;
    	}
    	public void setOffset(int offset) {
    		this.offset = offset;
    	}
    	public int getSize() {
    		return size;
    	}
    	public void setSize(int size) {
    		this.size = size;
    	}
    	public long getTotal() {
    		return total;
    	}
    	public void setTotal(long total) {
    		this.total = total;
    	}
    }
    

       在写完分页的类之后,接下来写DAO返回给service的东西,文件名是SystemContext.java

    package org.common.model;
    
    public class SystemContext {			//传分页需要把当前页和每页显示多少条
    	private static ThreadLocal<Integer> offset = new ThreadLocal<Integer>();
    	private static ThreadLocal<Integer> size = new ThreadLocal<Integer>();
    	
    	public static Integer getOffset() {
    		return offset.get();
    	}
    	public static void setOffset(Integer _offset) {
    		offset.set(_offset);
    	}
    	public static void removeOffset() {
    		offset.remove();
    	}
    	
    	public static Integer getSize() {
    		return size.get();
    	}
    	public static void setSize(Integer _size) {
    		size.set(_size);
    	}
    	public static void removeSize() {
    		size.remove();
    	}
    	
    }
    

      接下来实现IUserDao接口写UserDao类,文件名是UserDao.java

      在实现的同时,还要继承HibernateDaoSupport,extends HibernateDaoSupport

      但是在spring 的HibernateDaoSupport中,setSessionFactory是使用final 修饰的,无法重写,沒有办法使用注解的方式注入sessionFactroy

      所以可以自己定义一个方法,这个方法去调用hibernateDaoSupport 中的setSessionFacotry方法,达到注入sessionFactory 的目的。

      因此我定义如下的类:

    package org.common.dao;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.common.model.Pager;
    import org.common.model.SystemContext;
    import org.common.model.User;
    import org.hibernate.Query;
    import org.hibernate.SessionFactory;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    import org.springframework.stereotype.Repository;
    
    @Repository("userDao")			//申明一个DAO
    public class UserDao extends HibernateDaoSupport implements IUserDao {
    	
    	//但是在spring 的HibernateDaoSupport中,setSessionFactory是使用final 修饰的,无法重写,沒有办法使用注解的方式注入sessionFactroy
    	//所以可以自己定义一个方法,这个方法去调用hibernateDaoSupport 中的setSessionFacotry方法,达到注入sessionFactory 的目的。
    	@Resource
    	public void setSuperSessionFactory(SessionFactory sessionFactory) {	
    		this.setSessionFactory(sessionFactory);
    	}
    	
    	@Override
    	public void add(User user) {
    		this.getHibernateTemplate().save(user);
    	}
    
    	@Override
    	public void update(User user) {
    		this.getHibernateTemplate().update(user);
    	}
    
    	@Override
    	public void delete(int id) {
    		User user = this.load(id);
    		this.getHibernateTemplate().delete(user);
    	}
    
    	@Override
    	public User load(int id) {
    		return this.getHibernateTemplate().load(User.class, id);
    	}
    
    	@SuppressWarnings("unchecked")
    	@Override
    	public List<User> list() {
    		return this.getSession().createQuery("from User").list();
    	}
    
    	@SuppressWarnings("unchecked")
    	@Override
    	public Pager<User> find() {
    		int size = SystemContext.getSize();
    		int offset = SystemContext.getOffset();
    		Query query = this.getSession().createQuery("from User");
    		query.setFirstResult(offset).setMaxResults(size);
    		List<User> datas = query.list();
    		Pager<User> us = new Pager<User>();
    		us.setDatas(datas);
    		us.setOffset(offset);
    		us.setSize(size);
    		long total = (Long)this.getSession()
    					.createQuery("select count(*) from User")
    					.uniqueResult();
    		us.setTotal(total);
    		return us;
    	}
    
    	@Override
    	public User loadByUsername(String username) {
    		return (User)this.getSession().createQuery("from User where username=?")
    					.setParameter(0, username).uniqueResult();
    	}
    
    }
    
  • 相关阅读:
    Assembly介绍
    How to be a Programmer
    (转) 展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告
    ClientScript.RegisterStartupScript()
    sql server日期时间转字符串
    GridView 全选
    C# 获取xml里的值
    web 点击按钮,根据点击确认进行下一步操作
    字符串宽相同
    FormClosing
  • 原文地址:https://www.cnblogs.com/tonglin0325/p/6242420.html
Copyright © 2020-2023  润新知