javaEE之MVC三层架构及注册登入案例

一、MVC之三层架构

1、Servlet和JSP(模型1:JSP+javabean)

最佳实践:Servlet处理逻辑,把结果封装到域对象中(ServletRequest、HttpSession、ServletContext),转发给JSP,让JSP只负责显示。

数据的封装要用到JavaBean。架构思路如下:


2、MVC和三层架构图(模型2)

降低了各层之间的依赖,方便后期扩展与维护


3、开发顺序:

(1)javabean开始 com.fengyuwuzu.domain

封装数据,名词:用户

(2)业务接口com.fengyuwuzu.service

BusinessService:

void regist(User user) throws UserExistException;

User login(String username,String password);

(3)DAO接口com.fengyuwuzu.dao

void save(User user);

User findUser(String username);

User findUser(String username,String password);

(4)DAO实现com.fengyuwuzu.dao.impl

public class UserDaoMySQLImpl implements UserDao

(5)业务实现com.fengyuwuzu.service.impl

public class BusinessServiceImpl implements BusinessService

(6)单元测试com.fengyuwuzu.test

(7)表现层:com.fengyuwuzu.web.controller

html+jsp+servlet。LoginServlet+LogoutServlet+RegistServlet

(8)工具类com.fengyuwuzu.util

JdbcUtil、FillBeanUtil

二、登入注册案例

1、创建javabean及数据库表:

首先我们根据目的,来创建javabean,我们希望实现登入和注册,那么现在我们针对是用户注册信息。

public class User implements Serializable {
	private String username;
	private String password;
	private String email;
	private Date birthday;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}。。。

use day15;
create table user(
username varchar(100) primary key,
password varchar(100) not null,
email varchar(100) not null,
birthday date
);

2、业务接口

有了javabean我们操作的对象也就明确了,这个时候我们要明确我们要做什么,现在我们要注册和登入,所以在业务逻辑层,我们要实现的是注册和登入函数。这里只是根据要设计的功能,写出接口函数。

//根据需求来定
//接口:把注释写的没有歧义
public interface BusinessService {
	/**
	 * 用户注册
	 * @param user 注册信息
	 * @throws UserExistException 如果注册用户名已经存在了,抛出此异常
	 */
	void regist(User user) throws UserExistException;
	/**
	 * 完成用户登录
	 * @param username 用户名
	 * @param password 密码
	 * @return 如果用户名或密码错误,要返回null
	 */
	User login(String username,String password);
}

3、DAO接口

我们明确了业务要实现的几个功能,而这些功能依赖于持久层的数据,我们要明确持久层的操作,即数据的保存和查找:

//不负责业务逻辑,只负责CRUD
public interface UserDao {
	/**
	 * 保存用户信息
	 * @param user
	 */
	void save(User user);
	/**
	 * 根据用户名查询用户
	 * @param username
	 * @return 如果不存在返回null
	 */
	User findUser(String username);
	/**
	 * 根据用户名和密码查询用户
	 * @param username
	 * @param password
	 * @return 如果不存在返回null
	 */
	User findUser(String username,String password);
}

4、DAO实现

明确了底层要进行数据的保存和查找,那么现在我们可以实现DAO层的具体实现,这样我就可以接着实现业务逻辑层的实现了。

DAO的实现就是:连接数据库,进行数据库的CRUD

public class UserDaoMySQLImpl implements UserDao {

	public void save(User user) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtil.getConnection();
			stmt = conn.createStatement();
			stmt.executeUpdate("insert into user (username,password,email,birthday) values ('"+user.getUsername()+"','"+user.getPassword()+"','"+user.getEmail()+"','"+user.getBirthday().toLocaleString()+"')");
		}catch(Exception e){
			throw new DaoException(e);
		}finally{
			JdbcUtil.release(rs, stmt, conn);
		}
	}

	public User findUser(String username) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtil.getConnection();
			stmt = conn.createStatement();
			rs = stmt.executeQuery("select * from user where username='"+username+"'");
			if(rs.next()){
				User user = new User();
				user.setUsername(rs.getString("username"));
				user.setEmail(rs.getString("email"));
				user.setBirthday(rs.getDate("birthday"));
				return user;
			}else{
				return null;
			}
		}catch(Exception e){
			throw new DaoException(e);
		}finally{
			JdbcUtil.release(rs, stmt, conn);
		}
	}

	public User findUser(String username, String password) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtil.getConnection();
			stmt = conn.createStatement();
			rs = stmt.executeQuery("select * from user where username='"+username+"' and password='"+password+"'");
			if(rs.next()){
				User user = new User();
				user.setUsername(rs.getString("username"));
				user.setEmail(rs.getString("email"));
				user.setBirthday(rs.getDate("birthday"));
				return user;
			}else{
				return null;
			}
		}catch(Exception e){
			throw new DaoException(e);
		}finally{
			JdbcUtil.release(rs, stmt, conn);
		}
	}

}

5、业务实现

我们实现了DAO接口,并具体实现了DAO操作的实现,那我们业务逻辑的实现就可以利用DAO的实现来操作数据库的内容了。

业务实现,是为servlet服务的,这样servlet就可以调用这里实现的方法操作到底层的数据了。

public class BusinessServiceImpl implements BusinessService {
	private UserDao dao = BeanFactory.getUserDao();
	public void regist(User user) throws UserExistException {
		if(user==null)
			throw new IllegalArgumentException("The param user can not be null");
		User dbUser = dao.findUser(user.getUsername());
		if(dbUser!=null){
			throw new UserExistException("The username \""+user.getUsername()+"\"用户已经存在");
		}
		dao.save(user);
	}

	public User login(String username, String password) {
		return dao.findUser(username, password);
	}

}

6、单元测试

之上我们实现了业务逻辑和DAO层的东西,那么现在我们可以进行单元测试,测试业务逻辑层对数据库的操作是否都是正常的,一旦测试通过,证明我们业务逻辑都已经完全打通,可以交给表现层调用了

7、表现层

用户点击-->触发 servlet被调用-->servlet里面创建业务逻辑的实例,来调用里面的方法-->持久层数据被操作。

(1)首页jsp:

  <body>
    <h1>XX网站</h1>
    <hr/>
    <c:if test="${sessionScope.user==null}">
    	<a href="${pageContext.request.contextPath}/regist.jsp">注册</a>
    	<a href="${pageContext.request.contextPath}/login.jsp">登录</a>
    </c:if>
    <c:if test="${sessionScope.user!=null}">
    	欢迎您:${sessionScope.user.username}
    	<a href="${pageContext.request.contextPath}/servlet/LogoutServlet">注销</a>
    </c:if>
  </body>

(2)注册jsp

  <body>
    <form action="${pageContext.request.contextPath}/servlet/RegistServlet" method="post" enctype="application/x-www-form-urlencoded">
    	<!-- 
    	约定优于编码:遵守好的约定,会使代码编写更加高效
    	目前约定:表单的字段名和JavaBean的属性名保持了一致
    	 -->
    	<table border="1" width="738">
    		<tr>
    			<td>用户名:</td>
    			<td>
    				<input type="text" name="username" value="${formBean.username}"/>${formBean.errors.username}
    			</td>
    		</tr>
    		<tr>
    			<td>密码:</td>
    			<td>
    				<input type="password" name="password" value=""/>${formBean.errors.password}
    			</td>
    		</tr>
    		<tr>
    			<td>确认密码:</td>
    			<td>
    				<input type="password" name="repassword"/>${formBean.errors.repassword}
    			</td>
    		</tr>
    		<tr>
    			<td>邮箱:</td>
    			<td>
    				<input type="text" name="email" value="${formBean.email}"/>${formBean.errors.email}
    			</td>
    		</tr>
    		<tr>
    			<td>生日yyyy-MM-dd:</td>
    			<td>
    				<input type="text" name="birthday" value="${formBean.birthday}" readonly="readonly" onClick="return showCalendar('birthday', 'yy-mm-dd');"/>${formBean.errors.birthday}
    			</td>
    		</tr>
    		<tr>
    			<td colspan="2">
    				<input type="submit" value="注册"/>
    			</td>
    		</tr>
    	</table>
    </form>
  </body>
(3)登入jsp

 <body>
    <form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post" enctype="application/x-www-form-urlencoded">
    	<table border="1" width="438">
    		<tr>
    			<th>用户名:</th>
    			<td>
    				<input type="text" name="username"/>
    			</td>
    		</tr>
    		<tr>
    			<th>密码:</th>
    			<td>
    				<input type="text" name="password"/>
    			</td>
    		</tr>
    		<tr>
    			<td colspan="2">
    				<input type="submit" value="登录"/>
    			</td>
    		</tr>
    	</table>
    </form>
  </body>
(4)RegistServlet
//编码重点。完成注册
public class RegistServlet extends HttpServlet {
	private BusinessService s = new BusinessServiceImpl();
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String encoding = "UTF-8";
		request.setCharacterEncoding(encoding);
		response.setContentType("text/html;charset="+encoding);
		
		//获取表单数据,封装到JavaBean中。引入FormBean:特点属性和表单字段完全一致。且都是String类型。封装错误消息。
		UserFormBean formBean = FillBeanUtil.fillBean(request, UserFormBean.class);
		//数据验证:服务器端验证。实际开发中:客户端+服务器端验证。
		if(!formBean.validate()){
			//不通过:回显数据,消息提示
			request.setAttribute("formBean", formBean);
			request.getRequestDispatcher("/regist.jsp").forward(request, response);
			return;
		}
		
		//填充模型:formBean---->JavaBean
		User user = new User();
//		user.setUsername(formBean.getUsername());
//		user.setPassword(formBean.getPassword());
//		user.setEmail(formBean.getEmail());
//		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//		try {
//			user.setBirthday(df.parse(formBean.getBirthday()));
//		} catch (ParseException e) {
//			e.printStackTrace();
//		}
		
		ConvertUtils.register(new DateLocaleConverter(), Date.class);//注册类型转换器
		try {
			BeanUtils.copyProperties(user, formBean);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//通过:调用Service保存数据
		try {
			s.regist(user);
			response.getWriter().write("保存成功!2秒后转向主页");
			response.setHeader("Refresh", "2;URL="+request.getContextPath());
		} catch (UserExistException e) {
			//数据回显和提示
			formBean.getErrors().put("username", "用户名已经存在了");
			request.setAttribute("formBean", formBean);
			request.getRequestDispatcher("/regist.jsp").forward(request, response);
			return;
		}
	}
(5)LoginServlet
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String encoding = "UTF-8";
		request.setCharacterEncoding(encoding);
		response.setContentType("text/html;charset="+encoding);
		
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		User user = s.login(username, password);
		if(user==null){
			//错误的用户名或密码
			response.getWriter().write("错误的用户名或密码。2秒后转向登录页面。");
			response.setHeader("Refresh", "2;URL="+request.getContextPath()+"/login.jsp");
			return;
		}
		
		//登录成功
		request.getSession().setAttribute("user", user);
		response.getWriter().write("登录成功。2秒后转向主页。");
		response.setHeader("Refresh", "2;URL="+request.getContextPath());
		
	}
(6)LogoutServlet
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String encoding = "UTF-8";
		request.setCharacterEncoding(encoding);
		response.setContentType("text/html;charset="+encoding);
		
		request.getSession().removeAttribute("user");
//		request.getSession().invalidate();
		response.getWriter().write("注销成功。2秒后转向主页。");
		response.setHeader("Refresh", "2;URL="+request.getContextPath());
	}
8、工具类

为了简化代码,避免重复性的代码,将常用的代码抽取出来。如数据库操作,javabean填充等

(1)JdbcUtil

//与具体的数据库解耦
public class JdbcUtil {

	private static String driverClass;
	private static String url;
	private static String user;
	private static String password;
	
	static{
		try {
			InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbcfg.properties");
			Properties props = new Properties();
			props.load(in);
			
			driverClass = props.getProperty("driverClass");
			url = props.getProperty("url");
			user = props.getProperty("user");
			password = props.getProperty("password");
			Class.forName(driverClass);
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
		
	}

	public static Connection getConnection() throws Exception {
		Connection conn = DriverManager.getConnection(url,user,password);
		return conn;
	}

	public static void release(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

(2)填充javabean

依赖于:

commons-beanutils-1.8.3.jar

commons-logging-1.1.1.jar

public class FillBeanUtil {
	public static <T> T fillBean(HttpServletRequest request,Class<T> clazz){
		try {
			T bean = clazz.newInstance();
			BeanUtils.populate(bean, request.getParameterMap());
			return bean;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

(3)BeanFactory

public class BeanFactory {
	
	private static String userDao;
	static{
		try {
			InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dao.properties");
			Properties props = new Properties();
			props.load(in);
			userDao = props.getProperty("userDao");
		} catch (IOException e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static UserDao getUserDao(){
		try {
			return (UserDao) Class.forName(userDao).newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}


myeclipse工程代码下载:

http://download.csdn.net/detail/fengyuwuzu0519/9899979



  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值