Spurs

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Author:相忠良
Email: ugoood@163.com
起始于:May 2, 2018
最后更新日期:May 12, 2018

声明:本笔记依据传智播客方立勋老师 Java Web 的授课视频内容记录而成,中间加入了自己的理解。本笔记目的是强化自己学习所用。若有疏漏或不当之处,请在评论区指出。谢谢。
涉及的图片,文档写完后,一次性更新。

day0910 JSP 与案例

1. jsp 与 javabean

新建 day09 web 项目。

什么是 JavaBean?
答:JavaBean通常用于封装数据,它是遵循特定写法的java类,通常有如下特点:

  • 这个java类必须有一个无参构造函数;
  • 属性必须私有化;
  • 私有化属性必须由public类型的setter或getter方法暴露给其他程序,且方法命名需遵守一定的命名规范。

jsp 提供了三个关于 JavaBean 组件的动作元素,即 jsp 标签,分别为:

  • <jsp:useBean>:用于在 jsp 页面中查找或实例化1个 JavaBean 组件;
  • <jsp:setProperty>:相当于 setter 方法;
  • <jsp:getProperty>:相当于 getter 方法。

jsp中通过使用<jsp:useBean>标签,返回1个 JavaBean 对象(若对象存在,返回该对象,若不存在就 new 1个新的 JavaBean 对象并存到指定域中)。

在 cn.wk.domain 包中建立 Person 类:

package cn.wk.domain;

public class Person {
	private String name = "张三";
	private int age;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

新建 1.jsp 文件,代码如下:

<body>
  <jsp:useBean id="person" class="cn.wk.domain.Person" scope="page"></jsp:useBean>
  <%=person.getName() %>
</body>

上面代码,从 page 域查找 person 对象,若无则建。
查看 1.jsp 翻译后的java代码片段,如下:

cn.wk.domain.Person person = null;

person = (cn.wk.domain.Person) _jspx_page_context.getAttribute("person", javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (person == null){
  person = new cn.wk.domain.Person();
  _jspx_page_context.setAttribute("person", person, javax.servlet.jsp.PageContext.PAGE_SCOPE);
}

浏览器打开1.jsp,查看结果。

<jsp:useBean>标签的内容只在创建 JavaBean 实例的时候才执行。如下:

<body>
  <jsp:useBean id="person" class="cn.wk.domain.Person" scope="session">
    bbbbb  <%-- 此处只有创建 javabean 实例时才执行 --%>
  </jsp:useBean>

  <%=person.getName() %>
</body>

注意,上面代码 scope="session",意味着只要会话不关闭,person 对象就一直存在。若存在的话,<jsp:useBean>标签的内容就不会再次执行。

2.jsp涉及4个内容:

  • 手工为bean属性赋值;
  • 用请求参数给bean的属性赋值;
  • 用所有请求参数为 bean 的属性赋值;
  • jsp:getProperty标签直接输出。

2.jsp如下:

<body>
  <jsp:useBean id="person" class="cn.wk.domain.Person"/>

  <!-- 手工为 bean 属性赋值 -->
  <jsp:setProperty name="person" property="name" value="xxxx"/>
  <%=person.getName() %><br/>

  <!-- 用请求参数给bean的属性赋值 -->
  <!-- http://localhost:8080/day09/2.jsp?name=uuu&age=18 -->
  <jsp:setProperty property="name" name="person" param="name"/>
  <jsp:setProperty property="age" name="person" param="age"/>
  <%=person.getName() %><br/>
  <%=person.getAge() %><br/>

  <br/>---------------------------<br/>

  <!-- 用所有请求参数为 bean 的属性赋值 -->
  <jsp:setProperty property="*" name="person"/>
  <%=person.getName() %><br/>
  <%=person.getAge() %><br/>

  <!-- getProperty标签输出为字符串,为空时输出 null 字符串 -->
  <jsp:getProperty property="name" name="person"/><br/>
  <jsp:getProperty property="age" name="person"/>

</body>

注意:getProperty标签输出为字符串,为空时输出 null 字符串。

2. jsp 开发模式和 web 计算器案例

jsp 开发模式:

  • jsp + javabean
  • servlet + jsp + javabean

double 不能进行精确货币运算,BigDecimal 可进行精确货币运算。如下:

// 不精确计算
// double a=0.1;
// double b=0.006;
// System.out.println(a+b);

// 精确计算
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.006");
System.out.println(a.add(b));
System.out.println(a.divide(b, 10, BigDecimal.ROUND_CEILING));

web 计算器完整案例如下:

cn.wk.domain.CulculatorBean 类如下:

public class CulculatorBean {
	private String firstNum = "0";
	private char operator = '+';
	private String secondNum = "0";
	private String result;

	public void calculate() {
		BigDecimal firstNum = new BigDecimal(this.firstNum);
		BigDecimal secondNum = new BigDecimal(this.secondNum);
		switch (this.operator) {
		case '+': {
			this.result = firstNum.add(secondNum).toString();
			break;
		}
		case '-': {
			this.result = firstNum.subtract(secondNum).toString();
			break;
		}
		case '*': {
			this.result = firstNum.multiply(secondNum).toString();
			break;
		}
		case '/': {
			if (secondNum.doubleValue() == 0) {
				throw new RuntimeException("除数为0!");
			}
			this.result = firstNum.divide(secondNum, 10,
					BigDecimal.ROUND_HALF_UP).toString();
			break;
		}

		default:
			throw new RuntimeException("运算符错误!");
		}
	}

	public String getFirstNum() {
		return firstNum;
	}

	public void setFirstNum(String firstNum) {
		this.firstNum = firstNum;
	}

	public char getOperator() {
		return operator;
	}

	public void setOperator(char operator) {
		this.operator = operator;
	}

	public String getSecondNum() {
		return secondNum;
	}

	public void setSecondNum(String secondNum) {
		this.secondNum = secondNum;
	}

	public String getResult() {
		return result;
	}

	public void setResult(String result) {
		this.result = result;
	}
}

calculator.jsp 如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>计算器</title>
  </head>

  <body>
  	<jsp:useBean id="calculator" class="cn.wk.domain.CulculatorBean" scope="page"/>
  	<jsp:setProperty property="*" name="calculator"/>
  	<%
  		try {
  			calculator.calculate();
  		} catch (Exception e) {
  			out.write(e.getMessage());
  		}
  	%>

  	<br/>-----------------------------------------------<br/>
  	计算结果是:<jsp:getProperty property="firstNum" name="calculator"/>
  	<jsp:getProperty property="operator" name="calculator"/>
  	<jsp:getProperty property="secondNum" name="calculator"/>
  	=
  	<jsp:getProperty property="result" name="calculator"/>
  	<br/>-----------------------------------------------<br/>  	

  <form action="/day09/calculator.jsp" method="post">
    <table width=40% border="1">
    	<tr>
    		<td colspan="2">简单的计算器</td>
    	</tr>

    	<tr>
    		<td>第一个参数</td>
    		<td>
    			<input type="text" name="firstNum">
    		</td>
    	</tr>

    	<tr>
    		<td>操作符</td>
    		<td>
    			<select name="operator">
    				<option value="+">+</option>
    				<option value="-">-</option>
    				<option value="*">*</option>
    				<option value="/">/</option>
    			</select>
    		</td>
    	</tr>

    	<tr>
    		<td>第二个参数</td>
    		<td>
    			<input type="text" name="secondNum">
    		</td>
    	</tr>

    	<tr>
    		<td colspan="2">
    			<input type=submit value="计算">
    		</td>
    	</tr>    	
    </table>
    </form>
  </body>
</html>

3. MVC 开发模式

下图为 mvc 开发模式图,也包含了三层架构。
1

上图中为方便层的分离,设立了dao 接口,service接口。
因jsp是view,用户直接访问的话,并无数据。所以应将jsp保护起来,保护方法是在 WEB-INF 目录下建立jsp目录,并将jsp文件放入该目录。
上图又展示了各种包名。
针对 jsp 页面中不能写 java 代码的要求,就需用到 EL 表达式和 jstl。后面学它们。

4. EL 表达式和 JSTL 快速入门

EL表达式:用来输出数据。

关于EL的列子,day09项目的 3.jsp 和 javabean 文件 Person.java:

<body>
  <%
    String data="aaa";
    request.setAttribute("data", data);
  %>

  ${data} <%-- 相当于 pageContext.findArrtibute("data"); page->reuquest->session->application --%>
</body>
package cn.wk.domain;

public class Person {
	private String name="张三";
	private int age;

	public Person() {
		super();
	}
	public Person(String name) {
		super();
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

例:用 jstl + el 完成集合迭代,4.jsp:
涉及使用指令<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>,它可从工程中的JSTL 1.2.1 Libraryjstl-impl.jarWEB-INF目录中c.tld文件中的<uri>标签中找到。

<%@ page language="java" import="java.util.*,cn.wk.domain.Person"
	pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用jstl+el完成集合迭代</title>
</head>

<body>
	<!-- 迭代list集合 -->
	<%
		List list = new ArrayList();
		list.add(new Person("zhang6"));
		list.add(new Person("zhang4"));
		list.add(new Person("zhang5"));

		request.setAttribute("list", list);
	%>

	<c:forEach var="person" items="${list}">
  		${person.name}<br />
	</c:forEach>

	<br />-----------------------------------<br />

	<!-- 迭代map集合 -->
	<%
		Map map = new LinkedHashMap();
		map.put("aa", new Person("aaaa"));
		map.put("bb", new Person("bbbb"));
		map.put("cc", new Person("cccc"));
		map.put("dd", new Person("dddd"));
		map.put("11", new Person("eeee")); // 这可能出问题,看下面解决方法

		request.setAttribute("map", map);
	%>

	<c:forEach var="entry" items="${map}">
		${entry.key} : ${entry.value.name}<br />
	</c:forEach>

</body>
</html>

关于 if 的标签:

<!-- 代表用户登录了 -->
<c:if test="${user!=null}">欢迎您:${user.username}</c:if>

<c:if test="${user==null}">
  用户名:<input type="text"> <br />
  密码:<input type="text">
</c:if>

5. mvc 案例

项目名字:day09_user
功能:开发一个用户注册和登录功能,数据库用users.xml文件模拟。
方立勋老师提示:“Web 应用不管哪个模块的开发,其实都大同小异,希望所有同学通过这个用户模块,掌握一个软件的开发步骤,并认真体会软件三层架构开发思想!!!!!并且课后一定要自己动手去写!!!”

  1. 搭建开发环境
    1.1 导开发包:
    -- dom4j(dom4j-1.6.1.jar)
    -- jstl(我电脑建工程时自带)
    -- beanUtils(commons-beanutils-1.7.0.jar)
    -- log4j(commons-logging-1.1.jar)
    1.2 创建组织程序包:
    -- cn.wk.domain
    -- cn.wk.dao
    -- cn.wk.dao.impl
    -- cn.wk.service
    -- cn.wk.service.impl
    -- cn.wk.web.controller (处理请求的servlet)
    -- cn.wk.web.UI (为用户提供用户界面)
    -- cn.wk.utils
    -- junit.test
    -- WEB-INF/jsp 目录保存网站所有的 jsp
    1.3 创建代表数据库的xml文件
    -- 在类目录下创建一个代表数据库的users.xml文件

5.1 代码目录结构

2

3

代码思路待整理。

5.2 WebRoot中的代码

3

index.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>首页</title>
</head>

<body style="text-align:center;">

	<h1>xxxx网站</h1>
	<br />
	<div style="text-align:right;">
		<c:if test="${user!=null}">
  		欢迎您:${user.nickname} <a href="${pageContext.request.contextPath}/servlet/LogoutServlet">注销</a>
		</c:if>

		<c:if test="${user==null}">
			<a
				href="${pageContext.request.contextPath}/servlet/RegisterUIServlet">注册</a>
			<a href="${pageContext.request.contextPath}/servlet/LoginUIServlet">登录</a>
		</c:if>
	</div>
	<hr>

</body>
</html>

message.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>网站全局消息显示</title>
  </head>

  <body>
    ${message}
  </body>
</html>

login.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录界面</title>
<%-- <link tpye="text/css" rel="stylesheet"
	href="${pageContext.request.contextPath}/css/login.css"> 加css--%>
</head>

<body>
	<div id="container">
		<div id="image">
			<div id="form">
				<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
					<div class="input">
						用户:<input class="inputtext" type="text" name="username" />
					</div>

					<div class="input">
						密码:<input class="inputtext" type="password" name="password" />
					</div>

					<div id="btn">
						<input class="btn" type="button" value="注册"
							onclick="window.location.href='register.jsp'" />
						<input class="btn" type="submit" value="登录" />
					</div>
				</form>
			</div>
		</div>
	</div>
</body>
</html>

register.jsp如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/> <!-- 这可能是个坑 -->
<title>注册界面</title>
</head>

<body>
	<div id="header">
		这是页头,可添加图片<img src="">
	</div>

	<div id="main">
		<div id="notice">
			<h2>注册须知:</h2>
			1. 需遵守法律; 2. 在本网站发表的文章,本站都具有最终编辑权。
		</div>

		<form
			action="${pageContext.request.contextPath}/servlet/RegisterServlet"
			method="post">

			<table id="formtable">
				<tr>
					<td>登录账号:</td>
					<td>
						<input type="text" name="username" value="${form.username}">
						<span>${form.errors.username}</span>
					</td>
				</tr>

				<tr>
					<td>密码:</td>
					<td>
						<input type="password" name="password" value="${form.password}">
						<span>${form.errors.password}</span>
					</td>
				</tr>

				<tr>
					<td>确认密码:</td>
					<td>
						<input type="password" name="password2" value="${form.password2}">
						<span>${form.errors.password2}</span>
					</td>
				</tr>

				<tr>
					<td>电子邮箱:</td>
					<td>
						<input type="text" name="email" value="${form.email}">
						<span>${form.errors.email}</span>
					</td>
				</tr>

				<tr>
					<td>生日:</td>
					<td>
						<input type="text" name="birthday" id="birthday"
						title="点击选择" onClick="showCalendar(this.id)" value="${form.birthday}">
						<span>${form.errors.birthday}</span>
					</td>
				</tr>

				<tr>
					<td>您的昵称:</td>
					<td>
						<input type="text" name="nickname" value="${form.nickname}">

						<span>${form.errors.nickname}</span>
					</td>
				</tr>

				<tr>
					<td>图片认证:</td>
					<td><input type="text" name="checkcode"><img src="#" height="20px"></td>
				</tr>
			</table>

			<div id="formsubmit">
				<span><input type="reset" name="reset" value="重 置"></span>
				&nbsp;&nbsp; <span><input type="submit" name="submit"
					value="注 册"></span>
			</div>

		</form>
	</div>

	<div id="footer">这是页脚,也可添加图片</div>
</body>
</html>

5.3 src目录中的代码

2

模拟数据库的 users.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<users>
	<user id="20160918" username="aaa" password="123" email="aa@sina.com" birthday="1980-09-09"
		nickname="小强" />
</users>

UserDao:

package cn.wk.dao;
public interface UserDao {

	void add(User user);

	User find(String username, String password);

	// 查找注册的用户是否在数据库中存在
	boolean find(String username);
}

UserDaoImpl:

package cn.wk.dao.impl;

public class UserDaoImpl implements UserDao {
	public void add(User user) {
		try {
			Document document = XmlUtils.getDocument();
			Element root = document.getRootElement();

			Element user_tag = root.addElement("user");
			user_tag.setAttributeValue("id", user.getId());
			user_tag.setAttributeValue("username", user.getUsername());
			user_tag.setAttributeValue("password", user.getPassword());
			user_tag.setAttributeValue("email", user.getEmail());
			user_tag.setAttributeValue("birthday",
					user.getBirthday() == null ? "" : user.getBirthday()
							.toLocaleString());
			user_tag.setAttributeValue("nickname", user.getNickname());

			XmlUtils.write2Xml(document);

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public User find(String username, String password) {
		try {
			Document document = XmlUtils.getDocument();
			// 从所有的user标签中查找用户应和密码匹配的
			Element e = (Element) document
					.selectSingleNode("//user[@username='" + username
							+ "' and @password='" + password + "']");
			if (e == null)
				return null;

			User user = new User();
			String date = e.attributeValue("birthday"); // "" 1980-09-09
			if (date == null || date.equals("")) {
				user.setBirthday(null);
			} else {
				SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
				user.setBirthday(df.parse(date));
			}

			user.setEmail(e.attributeValue("email"));
			user.setId(e.attributeValue("id"));
			user.setNickname(e.attributeValue("nickname"));
			user.setPassword(e.attributeValue("password"));
			user.setUsername(e.attributeValue("username"));
			return user;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// 查找注册的用户是否在数据库中存在
	public boolean find(String username) {
		try {
			Document document = XmlUtils.getDocument();

			Element e = (Element) document
					.selectSingleNode("//user[@username='" + username + "']");
			if (e == null)
				return false;
			else
				return true;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

User:

package cn.wk.domain;

import java.util.Date;

public class User {
	private String id;
	private String username;
	private String password;
	private String email;
	private Date birthday;
	private String nickname;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	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;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
}

UserExistException:

package cn.wk.exception;
public class UserExistException extends Exception {
	public UserExistException() {
		// TODO Auto-generated constructor stub
	}

	public UserExistException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public UserExistException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}

	public UserExistException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public UserExistException(String message, Throwable cause,
			boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}
}

BusinessService:

package cn.wk.service;

public interface BusinessService {

	// 对web层提供注册服务
	void register(User user) throws UserExistException;

	// 对web层提供登录服务
	User login(String username, String password);
}

BusinessServiceImpl:

package cn.wk.service.impl;

// 对 web 层提供所有的业务服务
public class BusinessServiceImpl implements BusinessService {

	private UserDao dao = new UserDaoImpl(); // 可用工厂模式 或 spring 解耦,以后解耦

	// 对web层提供注册服务
	public void register(User user) throws UserExistException {
		// 先判断当前要注册的用户是否存在
		boolean b = dao.find(user.getUsername());
		if (b) {
			// 发现要注册的用户已存在,则给web层抛checked异常,提醒web层处理这个异常,给用户一个友好提示
			throw new UserExistException();
		} else {
			user.setPassword(ServiceUtils.md5(user.getPassword()));
			dao.add(user);
		}
	}

	// 对web层提供登录服务
	public User login(String username, String password) {// aaa 123
		password = ServiceUtils.md5(password);
		return dao.find(username, password);
	}
}

ServiceUtils:

package cn.wk.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import sun.misc.BASE64Encoder;

public class ServiceUtils {

	public static String md5(String message) {

		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			byte[] md5 = md.digest(message.getBytes());

			BASE64Encoder encoder = new BASE64Encoder();
			return encoder.encode(md5);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}
}

WebUtils:

package cn.wk.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

public class WebUtils {

	// 传进来的类型是 T,该方法返回的对象类型也是 T,用到泛型
	public static <T> T request2Bean(HttpServletRequest request,
			Class<T> beanClass) {

		try {
			// 1. 创建要封装数据的bean
			T bean = beanClass.newInstance();

			// 2. 把request中数据整到bean中
			Enumeration e = request.getParameterNames();
			while(e.hasMoreElements()){
				//username password email birthday
				String name = (String) e.nextElement();
				// aaaa 123 aa@aaa.com 1980-01-01
				String value = request.getParameter(name);
				BeanUtils.setProperty(bean, name, value);
			}
			return bean;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// 想把 form 转成 user
	public static void copyBean(Object src, Object dest){

		/*
		form:
		private String username;
		private String password;
		private String password2;
		private String email;
		private String birthday;
		private String nickname;
		private Map errors = new HashMap();

		user:
		private String id;
		private String username;
		private String password;
		private String email;
		private Date birthday;
		private String nickname;		
		*/

		// 两个 bean 属性不同,需注册一个日期转换器
		ConvertUtils.register(new Converter() {
			@Override
			public Object convert(Class type, Object value) {
				if (value == null) {
					return null;
				}
				String str = (String) value;
				if (str.trim().equals("")) {
					return null;
				}

				// 此时无 1980-11-32 这种情况了
				SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
				try {
					return df.parse(str);
				} catch (ParseException e) {
					throw new RuntimeException(e);
				}
			}
		}, Date.class);

		try {
			BeanUtils.copyProperties(dest, src);
		} catch (Exception e) {			
			throw new RuntimeException(e);
		}
	}

	// 为user的id属性产生全球唯一的id
	public static String generateID(){
		return UUID.randomUUID().toString();
	}
}

XmlUtils:

package cn.wk.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class XmlUtils {

	// 获取 xml 文件路径
	private static String filepath;
	static {
		filepath = XmlUtils.class.getClassLoader().getResource("users.xml")
				.getPath();
	}

	public static Document getDocument() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File(filepath));
		return document;
	}

	public static void write2Xml(Document document) throws Exception {
		// Pretty print the document to System.out
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("UTF-8");
		XMLWriter writer = new XMLWriter(new FileOutputStream(filepath), format);
		writer.write(document);
		writer.close();
	}
}

LoginServlet:

package cn.wk.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.wk.domain.User;
import cn.wk.service.impl.BusinessServiceImpl;

// 处理登录请求
public class LoginServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		request.setCharacterEncoding("UTF-8");
		String username = request.getParameter("username");
		String password = request.getParameter("password");

		BusinessServiceImpl service = new BusinessServiceImpl();
		User user = service.login(username, password);
		if (user != null) {
			// 登录成功后,session中存个登录标记
			request.getSession().setAttribute("user", user);
			// 跳转到首页
			response.sendRedirect(request.getContextPath() + "/index.jsp");
			return;
		}

		// 用户名 密码 不匹配
		request.setAttribute("message", "用户名或密码错误!!");
		request.getRequestDispatcher("/message.jsp").forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

LogoutServlet:

package cn.wk.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

// 处理用户注销请求
public class LogoutServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		request.setCharacterEncoding("UTF-8");
		// 不创建新session,只得内存中的session
		HttpSession session = request.getSession(false);
		if (session != null) {
			session.removeAttribute("user"); // 移除注销标记
		}

		// 注销成功,跳到全局消息显示页面,显示注销成功消息,并控制消息显示页面过3秒后跳到首页
		request.setAttribute("message",
				"注销成功,浏览器将在3秒后调至首页!!<meta http-equiv='refresh' content='3;url="
						+ request.getContextPath() + "/index.jsp'>");
		request.getRequestDispatcher("/message.jsp").forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

RegisterServlet:

package cn.wk.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.wk.domain.User;
import cn.wk.exception.UserExistException;
import cn.wk.service.impl.BusinessServiceImpl;
import cn.wk.utils.WebUtils;
import cn.wk.web.formbean.RegisterForm;

// 处理注册请求
public class RegisterServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		request.setCharacterEncoding("UTF-8");

		// 1. 对提交表单的字段进行合法性校验(把表单数据封装到formbean)
		RegisterForm form = WebUtils.request2Bean(request, RegisterForm.class);
		boolean b = form.validate();

		// 2. 如果校验失败,跳回到表单页面,回显校验失败信息
		if(!b){
			request.setAttribute("form", form); // 传递错误消息
			request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(request, response);
			return;
		}

		// 3. 如果校验成功,则调用service处理注册请求
		User user = new User();
		WebUtils.copyBean(form, user); // 把form搞进user,得实现两个bean的拷贝
		user.setId(WebUtils.generateID());

		BusinessServiceImpl service = new BusinessServiceImpl();
		try {
			service.register(user);
			// 6. 如果service处理成功,则跳转到网站的全局消息显示页面,为用户显示注册成功的消息
			request.setAttribute("message", "恭喜您,注册成功!!");
			request.getRequestDispatcher("/message.jsp").forward(request, response);
			return;
		} catch (UserExistException e) {

			// 4. 如果service处理不成功,并且不成功的原因是注册用户已存在,则跳回到注册页面,显示注册用户已存在
			form.getErrors().put("username", "注册的用户名已存在!!");
			request.setAttribute("form", form);
			request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(
					request, response);
			return;
		}catch(Exception e){

			// 5. 如果service处理不成功,并且不成功的原因是其他问题的话,则跳转到网站的全局消息显示页面,为用户显示友好错误消息
			e.printStackTrace();
			request.setAttribute("message", "服务器出现未知错误!!!");
			request.getRequestDispatcher("/message.jsp").forward(
					request, response);
			return;
		}
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

RegisterForm:

package cn.wk.web.formbean;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;

public class RegisterForm {
	private String username;
	private String password;
	private String password2;
	private String email;
	private String birthday; // 小心,这里不是Date,该类将记录表单数据,全字符串
	private String nickname;

	// private String checkcode; // 以后再说

	private Map errors = new HashMap(); // 定义集合,存储失败消息,并传递给 service

	/*
	 * 对 对象进行校验,规则如下: 1. 用户名不能为空,并且是3-8位字母 2. 密码不为空,且3-8位数字 3.
	 * 确认密码不能为空,且要和第一次的一致 4. 电子邮箱不为空,且是一个合法邮箱 5. 生日可为空,不为空时,必须是一个日期 6.
	 * 昵称不可为空,且必是汉字
	 */
	public boolean validate() {
		boolean isOK = true;

		// 1. 用户名不能为空,并且是3-8位字母
		if (this.username == null || this.username.trim().equals("")) {
			isOK = false;
			errors.put("username", "用户名不能为空!!");
		} else {
			if (!this.username.matches("[A-Za-z]{3,8}")) {
				isOK = false;
				errors.put("username", "用户名必须为3-8位字母!!");
			}
		}

		// 2. 密码不为空,且3-8位数字
		if (this.password == null || this.password.trim().equals("")) {
			isOK = false;
			errors.put("password", "密码不能为空!!");
		} else {
			if (!this.password.matches("\\d{3,8}")) {
				isOK = false;
				errors.put("password", "密码必须为3-8位数字!!");
			}
		}

		// 3. 确认密码不能为空,且要和第一次的一致
		if (this.password2 == null || this.password2.trim().equals("")) {
			isOK = false;
			errors.put("password2", "确认密码不能为空!!");
		} else {
			if (!this.password.equals(this.password2)) {
				isOK = false;
				errors.put("password2", "两次密码要一致!!");
			}
		}

		// 4. 电子邮箱不为空,且是一个合法邮箱
		if (this.email == null || this.email.trim().equals("")) {
			isOK = false;
			errors.put("email", "电子邮箱不能为空!!");
		} else {
			if (!this.email.matches("\\w+@\\w+(\\.\\w+)+")) {
				isOK = false;
				errors.put("email", "电子邮箱格式不对!!");
			}
		}

		// 5. 生日可为空,不为空时,必须是一个日期
		if (this.birthday != null && !this.birthday.trim().equals("")) {
			try {// 日期格式校验 应该用这个
				DateLocaleConverter dlc = new DateLocaleConverter();
				dlc.convert(this.birthday, "yyyy-MM-dd");
			} catch (Exception e) {
				isOK = false;
				errors.put("birthday", "日期格式不对!!");
			}
		}

		// 6. 昵称不可为空,且必是汉字
		if (this.nickname == null || this.nickname.trim().equals("")) {
			isOK = false;
			errors.put("nickname", "昵称不能为空!!");
		}
		else {
			if (!this.nickname.matches("[\u4e00-\u9fa5]+")) {
				isOK = false;
				errors.put("nickname", "昵称必须是汉字!!");
			}
		}
		// 注意中文乱码问题:
		// 要在 RegisterServlet.java 中 加入 request.setCharacterEncoding("UTF-8");
		// 否则 表单输入中文后,取出来的是乱码,无法通过是否为汉字的测试

		return isOK; // 闯过前面所有关卡,isOK 为 true
	}

	public Map getErrors() {
		return errors;
	}

	public void setErrors(Map errors) {
		this.errors = errors;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPassword2() {
		return password2;
	}

	public void setPassword2(String password2) {
		this.password2 = password2;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getBirthday() {
		return birthday;
	}

	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}

	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
}

LoginUIServlet:

package cn.wk.web.UI;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 提供登录界面
public class LoginUIServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,
				response);
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

RegisterUIServlet:

package cn.wk.web.UI;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 为用户提供注册页面
public class RegisterUIServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(
				request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

ServiceTest:

package junit.test;

import java.util.Date;

import org.junit.Test;

import cn.wk.domain.User;
import cn.wk.exception.UserExistException;
import cn.wk.service.BusinessService;
import cn.wk.service.impl.BusinessServiceImpl;

public class ServiceTest {

	@Test
	public void testRegister(){

		User user = new User();
		user.setBirthday(new Date());
		user.setEmail("bb@163.com");
		user.setId("575638345");
		user.setNickname("小李子");
		user.setPassword("123");
		user.setUsername("ggg");

		BusinessService service = new BusinessServiceImpl();
		try {
			service.register(user);
			System.out.println("注册成功!");
		} catch (UserExistException e) {
			System.out.println("用户已存在!");
		}
	}

	@Test
	public void testLogin(){
		BusinessService service = new BusinessServiceImpl();
		User user = service.login("ggg", "123");
		System.out.println(user);
	}
}

UserDaoTest:

package junit.test;

import java.util.Date;

import org.junit.Test;

import cn.wk.dao.UserDao;
import cn.wk.dao.impl.UserDaoImpl;
import cn.wk.domain.User;

public class UserDaoTest {
	@Test
	public void testAdd() {
		User user = new User();
		user.setBirthday(new Date());
		user.setEmail("bb@163.com");
		user.setId("575638345");
		user.setNickname("小李子");
		user.setPassword("123");
		user.setUsername("bbb");

		UserDao dao = new UserDaoImpl();
		dao.add(user);
	}

	@Test
	public void testFind() {
		UserDao dao = new UserDaoImpl();
		dao.find("aaa", "123");
	}

	@Test
	public void testFindByName() {
		UserDao dao = new UserDaoImpl();
		System.out.println(dao.find("ssdaaa"));
	}
}

购物车开发模块,略过。

posted on 2018-05-12 10:51  英雄与侠义的化身  阅读(266)  评论(0编辑  收藏  举报