JavaWeb-13 (用户的注册和登录案例)
来源:互联网 发布:苹果mac怎么下载 编辑:程序博客网 时间:2024/06/06 07:20
JavaWeb-13:项目案例
用户注册和登录案例项目
一、用户注册和登录案例
1、技术架构:三层架构(表现层MVC:M:model V:View C:Controller)
2、要求:JSP中不能出现一行java脚本或java表达式。除了指令<%@%>,其余地方不能有<%%>
3、数据库:临时使用xml。解析使用Dom4j
4、必须知道要干什么?
5、开发步骤:
a、建立工程,搭建开发环境(拷贝jar包、建立配置文件) dom4j.jar jaxen.jar commons-beanutils.jar commons-logging.jar standard.jar jstl.jarb、建立类所用的包 cn.itcast.domain:放JavaBean 弄出数据库 cn.itcast.dao:放Dao接口 cn.itcast.dao.impl:放Dao接口的实现 cn.itcast.servcie:业务接口 cn.itcast.service.impl:业务接口实现 cn.itcast.web.controller:Servlet控制器 //WEB-INF/pages:用户无法直接访问(只能靠转发)
工程架构:
知识点:用户输入数据的验证
1、客户端验证:使用js代码。减轻服务器的负担2、服务器端验证:使用java代码。安全3、实际开发中:1+2
二、用户的注册和登录案例攻略
1、搭建环境:
创建好需要用来读取和存储的xml数据库文件--->导入jar包(用来操作xml数据库文件的Dom4J包、封装数据用的BeanUtils包、使用XPath的jaxen-1.1-beta-6.jar包),创建User类(JavaBean),用于关联每一层的数据。
User.java
package com.heima.bean;import java.io.Serializable;import java.util.Date;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; } 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; }}
2、设计业务逻辑层和数据访问层的接口
新建dao包:
接口类IUserDao:新建用于操作JavaBean数据的方法接口类IUserDao,里面提供添加用户并返回用户对象的方法addUser接口,提供根据用户的名字和密码查找用户,返回用户对象的方法findUserByUserNameAndPassword接口,提供根据用户的姓名查找用户的方法findUserByUserName接口。
IUserDao
package com.heima.dao;import com.heima.bean.User;public interface IUserDao { /** * 将用户添加到数据库 * @param user 要添加的用户 * @return 成功返回此用户,失败返回null */ public User addUser(User user) ; /** * 根据用户的名字和密码查找用户 * param username 用户名 * param password 用户的密码 * @return 找到用户返回此用户,否则返回null */ public User findUserByUserNameAndPassword(String username,String password ) ; /** * 根据用户的姓名查找用户 * @param username 用户的姓名 * @return 找到用户返回此用户,否则返回null */ public User findUserByUserName(String username) ;}
新建Utils包:
DBUtils类:该工具类主要用于获取xml里的数据和把数据写回xml文件的方法:
getDocument()和write2xml()方法。该类里使用了dom4J包里的工具类,例如创建dom4j解析器和写回xml文件的方法。
DBUtils.java
package com.heima.utils;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.io.OutputFormat;import org.dom4j.io.SAXReader;import org.dom4j.io.XMLWriter;//工具类public class DBUtils { public static String path ; static{ path = DBUtils.class.getClassLoader().getResource("users.xml").getPath() ; } //加载dom树 public static Document getDocument(){ try { //创建dom4j解析器 SAXReader reader = new SAXReader() ; //读取文档 Document document = reader.read(path) ; return document ; } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null ; } //将内存中的dom树写回到硬盘 public static void write2xml(Document document){ try { XMLWriter writer = new XMLWriter(new FileOutputStream(path),OutputFormat.createPrettyPrint()) ; writer.write(document) ; writer.close() ; } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
新建dao.impl包:
该包用于存储继承接口类IUserDao的实现类UserDaoImpl.java。该类的作用:
addUser()主要是通过调用Utils包里提供的方法getDocument()和write2xml(),把从别处生成的User对象里的属性数据写到xml文件里并返回该User对象,findUserByUserNameAndPassword()主要是通过Utils包工具加载到xml里,然后通过dom4j里的方法使用XPath和相对应的属性定位到要找的user对象,并判断如果存在就封装成user对象并返回,无就返回null。findUserByUserName()主要是通过传进来的属性并加载了xml文档后去使用XPath定位要找的user,如果不存在就返回一个新的User对象,若找到就返回null。
UserDaoImpl.java
package com.heima.dao.impl;import java.text.ParseException;import java.text.SimpleDateFormat;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.Node;import com.heima.bean.User;import com.heima.dao.IUserDao;import com.heima.utils.DBUtils;public class UserDaoImpl implements IUserDao { public User addUser(User user) { //获取dom树 Document document = DBUtils.getDocument() ; //获得根节点 Element root = document.getRootElement() ; //添加用户 root.addElement("user").addAttribute("username", user.getUsername()) .addAttribute("password", user.getPassword()) .addAttribute("email", user.getEmail()) .addAttribute("birthday", new SimpleDateFormat("yyyy-MM-dd").format(user.getBirthday())) ; //写回硬盘 DBUtils.write2xml(document) ; return user; } public User findUserByUserNameAndPassword(String username, String password) { //加载dom树 Document document = DBUtils.getDocument() ; //查找user节点 Node node = document.selectSingleNode("//user[@username='" + username + "' and @password='" + password+ "']") ; if(node != null){ //封装数据 User user = new User() ; Element el = (Element)node ; user.setUsername(el.valueOf("@username")) ; user.setPassword(el.valueOf("@password")) ; user.setEmail(el.valueOf("@email")) ; try { user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(el.valueOf("@birthday"))) ; } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return user ; } return null; } public User findUserByUserName(String username) { //加载dom树 Document document = DBUtils.getDocument() ; //查找user节点 Node node = document.selectSingleNode("//user[@username='" + username + "']") ; if(node != null){ return new User() ; } return null; }}
新建service包:
接口IUserService类:
该类的框架目的主要是让实现类去调用实现类UserDaoImpl.java里的功能。方法接口login():目的为了让实现类根据用户的姓名和密码完成用户的登录,方法接口:register()目的为了让实现类完成注册用户的功能。
IUserService.java
package com.heima.service;import com.heima.bean.User;import com.heima.exception.UserExistException;public interface IUserService { /** * 根据用户的姓名和密码完成用户的登录 * @param username 用户的姓名 * @param password 用户的密码 * @return 登录成功返回此用户,失败返回null */ public User login(String username,String password ) ; /** * 完成注册用户的功能 * @param user 要注册的用户 * @return 成功返回TRUE,失败返回FALSE * @throws UserExistException 如果用户存在抛出用户存在异常 */ public boolean register(User user) throws UserExistException;}
新建exception包:
UserExistException.java:
用于提供给UserServiceImpl类抛出异常。
UserExistException.java
package com.heima.exception;public class UserExistException extends Exception {}
新建service.impl包:
UserServiceImpl类:
在类里创建UserDaoImpl的对象,并使用UserDaoImpl对象里的方法去获得对应的User对象。 login():通过根据用户的姓名和密码来传入到UserDaoImpl对象的方法中去完成用户的登录,并返回User对象。 register():通过根据用户的姓名来传入到UserDaoImpl对象的方法中去完成用户的注册验证,并返回boolean值。还有判断如果用户存在抛出异常。
UserServiceImpl.java
package com.heima.service.impl;import com.heima.bean.User;import com.heima.dao.IUserDao;import com.heima.dao.impl.UserDaoImpl;import com.heima.exception.UserExistException;import com.heima.service.IUserService;public class UserServiceImpl implements IUserService { IUserDao dao = new UserDaoImpl() ; public User login(String username, String password) { return dao.findUserByUserNameAndPassword(username, password); } public boolean register(User user) throws UserExistException { //验证用户是否已经存在了 User u = dao.findUserByUserName(user.getUsername()) ; if(u != null){ //说明此用户已经存在了,需要抛出异常 throw new UserExistException() ; } User u1 = dao.addUser(user) ; return u1!=null ; }}
设计业务逻辑层和数据访问层的接口并实现步骤完成。
3、搭建表现层并连接各层间的关系
首先实现页面:新建index.jsp,写用于注册的register.jsp的超链和用于登录的login.jsp的超链
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <a href="http://blog.163.com/faith_yee/blog/register.jsp">注册</a> <a href="http://blog.163.com/faith_yee/blog/login.jsp">登陆</a> </body></html>
新建web.formbean包:
创建UserBean.java类:
该javabean类用于封装页面的数据和验证数据用的。类里除了各种属性和设置属性的方法之外,还有一个用来验证数据的方法validate(),就是从别处传来的各种属性都需要符合该方法里的规格,付过不符合,方法会为属性里的Map集合存储用于传达给页面的验证信息,并该方法最后返回boolean值反映存储的属性数据是否正确。
UserBean.java
package com.heima.web.formbean;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.HashMap;import java.util.Map;import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;//主要用来封装页面的数据,验证数据public class UserBean { private String username ; private String password ; private String repassword ; private String email ; private String birthday ; private Map<String,String> errors = new HashMap<String,String>() ; 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 getRepassword() { return repassword; } public void setRepassword(String repassword) { this.repassword = repassword; } 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 Map<String, String> getErrors() { return errors; } //检测数据 public boolean validate(){ //检测用户名 if(username == null || "".equals(username)){ errors.put("username", "用户名不能为空") ; }else{ if(username.length() < 3 || username.length() > 8){ errors.put("username", "用户名长度不符合要求") ; } } //检测密码 if(password == null || "".equals(password)){ errors.put("password", "密码不能为空") ; }else{ if(password.length() < 3 || password.length() > 8){ errors.put("password", "密码长度不符合要求") ; } } //检测重复密码 if(!repassword.equals(password)){ errors.put("password", "两次密码不一致") ; } //检测邮箱 String reg = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$" ; if(email == null || "".equals(email)){ errors.put("email", "邮箱不能为空") ; }else{ if(!email.matches(reg)){ errors.put("email", "邮箱格式不正确") ; } } //检测出生日期 if(birthday == null || "".equals(birthday)){ errors.put("birthday", "出生日期不能为空") ; }else{// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;// try {// sdf.parse(birthday) ;// } catch (ParseException e) {// errors.put("birthday", "日期格式不正确") ;// } DateLocaleConverter dlc = new DateLocaleConverter() ; try { dlc.convert(birthday) ; } catch (Exception e) { errors.put("birthday", "日期格式不正确") ; } } return errors.isEmpty() ; } }
在原来的Utils包:
新建WebUtils类:
该工具类用于给页面传进来的UserBean类中的属性数据还有页面发来的request请求进行使用反射技术生产对象:因为传来的类对象本来不存在,所以使用反射机制来处理生成对象,并使用BeanUtils包里的超级方法populate()把UserBean对象和页面中的属性和属性值包装起来,并返回。
WebUtils.java
package com.heima.utils;import javax.servlet.http.HttpServletRequest;import org.apache.commons.beanutils.BeanUtils;//为页面服务的工具类public class WebUtils { public static <T> T fillFormBean(Class<T> clazz,HttpServletRequest reqeust){ T t = null ; //创建对象 try { t = clazz.newInstance() ; BeanUtils.populate(t, reqeust.getParameterMap()) ; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return t ; }}
新建web.controls包:
新建RegisterServlet.java类:
用于处理页面register.jsp传进来的UserBean数据,并通过调用UserBean里的验证数据方法validate()验证页面传进来的数据是否有效,无效会跳转回register.jsp页面,然后BeanUtils.copyProperties()用于将数据从userBean中拷贝到user对象中,为存储到xml文档中的必然步骤。最后调用UserServiceImpl类中的register()方法注册用户,成功跳转到login.jsp页面,失败跳转回register.jsp页面。另外一种可能,如果register()抛出了异常,那么RegisterServlet.java就给异常处理。
RegisterServlet.java
package com.heima.web.controls;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;import com.heima.bean.User;import com.heima.exception.UserExistException;import com.heima.service.IUserService;import com.heima.service.impl.UserServiceImpl;import com.heima.utils.WebUtils;import com.heima.web.formbean.UserBean;//注册处理器public class RegisterServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8");// UserBean formuser = new UserBean() ;// try {// BeanUtils.populate(formuser, request.getParameterMap()) ;// } catch (IllegalAccessException e) {// // TODO Auto-generated catch block// e.printStackTrace();// } catch (InvocationTargetException e) {// // TODO Auto-generated catch block// e.printStackTrace();// } //接收页面数据,封装数据 UserBean userform = WebUtils.fillFormBean(UserBean.class, request) ; //验证数据是否有效 if(!userform.validate()){ //没有通过 request.setAttribute("userform", userform) ; request.getRequestDispatcher("/register.jsp").forward(request, response) ; return ; } //验证通过 //将数据从userBean中拷贝到user对象中 User user = new User() ; try { //注册时间转换器 ConvertUtils.register(new DateLocaleConverter(), Date.class) ; //拷贝数据 BeanUtils.copyProperties(user, userform) ; } catch (Exception e) { e.printStackTrace(); } //注册用户 IUserService us = new UserServiceImpl() ; try { boolean flag = us.register(user) ; if(flag){ //注册成功 response.getWriter().write("恭喜,注册成功,2秒后转向登陆页面") ; response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.jsp") ; }else{ response.getWriter().write("注册失败,2秒后转注册页面") ; response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/register.jsp") ; } } catch (UserExistException e) { //此用户已经注册过了 userform.getErrors().put("username", "此用户名已经注册了,请更换一个") ; request.setAttribute("userform", userform) ; request.getRequestDispatcher("/register.jsp").forward(request, response) ; } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
最后创建register.jsp:
利用el表达式把存到UserBean里的属性值通过submit按钮发送到指定的RegisterServlet里,register.jsp也会通过el表达式返回UserBean里Map类型的errors信息。
register.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'register.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <script type="text/javascript"> function formsubmit(form){ var username = form.username.value ; if(username == ""){ //alert("用户名不能为空") ; //return false ; } return true ; } </script> <body> <form action = "${pageContext.request.contextPath }/servlet/RegisterServlet" method="post" onsubmit="return formsubmit(this)"> <table border =1 > <tr> <td>${"用户名" }</td> <td><input type="text" name = "username" value = "${userform.username}">${userform.errors.username }</td> </tr> <tr> <td>${"密码" }</td> <td><input type="password" name = "password" value = "${userform.password }">${userform.errors.password }</td> </tr> <tr> <td>${"确认密码" }</td> <td><input type="password" name = "repassword" ></td> </tr> <tr> <td>${"邮箱" }</td> <td><input type="text" name = "email" value = "${userform.email }">${userform.errors.email }</td> </tr> <tr> <td>${"出生日期" }</td> <td><input type="text" name = "birthday" value = "${userform.birthday }">${userform.errors.birthday }</td> </tr> <tr> <td colspan = "2"><input type="submit" value = "注册"></td> </tr> </table> </form> </body></html>
还有其他类和jsp文件:如下:
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'register.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <script type="text/javascript"> function formsubmit(form){ var username = form.username.value ; if(username == ""){ //alert("用户名不能为空") ; //return false ; } return true ; } </script> <body> ${errorinfo } <form action = "${pageContext.request.contextPath }/servlet/LoginServlet" method="post" onsubmit="return formsubmit(this)"> <table border =1 > <tr> <td>${"用户名" }</td> <td><input type="text" name = "username" value = "${userform.username}">${userform.errors.username }</td> </tr> <tr> <td>${"密码" }</td> <td><input type="password" name = "password" value = "${userform.password }">${userform.errors.password }</td> </tr> <tr> <td colspan = "2"><input type="submit" value = "登陆"></td> </tr> </table> </form> </body></html>
LoginServlet.java
package com.heima.web.controls;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.heima.bean.User;import com.heima.service.IUserService;import com.heima.service.impl.UserServiceImpl;//实现登陆功能public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); //拿取页面传递的数据 String username = request.getParameter("username") ; String password = request.getParameter("password") ; //查找用户 //创建service层对象 IUserService us = new UserServiceImpl() ; User user = us.login(username, password) ; if(user != null){ //登陆成功 request.getSession().setAttribute("loginuser", user) ; response.getWriter().write("登陆成功,2秒后转向主页") ; response.setHeader("Refresh", "2;url="+ request.getContextPath() + "/main.jsp") ; }else{ //登陆失败 request.setAttribute("errorinfo", "用户名或者密码错误") ; request.getRequestDispatcher("/login.jsp").forward(request, response) ; } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'register.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> ${loginuser.username },欢迎你 </body></html>
表现层完成。
三、总结
用户--->register.jsp--->输入信息------>提交到RegisterServlet里,RegisterServlet结合UserBean类、UserServiceImpl类给用户注册----->注册成功后:数据会转到User类里,并通过业务逻辑层和数据访问层的类和方法把User类里的数据存储到xml数据库中。可以发现,我们搭建这个项目是和用户的思维完全相反的。
资料下载
- JavaWeb-13 (用户的注册和登录案例)
- 用户注册和登录案例
- 用户注册登录案例
- 用户登录注册案例
- MVC模型和JavaWeb模型入门_简单的注册登录案例
- 用户登录注册案例分析
- 用户登录注册案例分析
- 超全面的JavaWeb笔记day14<用户注册登录>
- MVC案例:用户的注册和登陆
- 用户注册和登录
- 简易的用户注册和登录系统.
- Ucenter的用户注册和登录分析
- Ucenter的用户注册和登录分析
- Javaweb 登录注册的实现
- 简单的Javaweb登录注册
- 黑马程序员_用户登录注册案例
- GUI_用户登录注册加入四则运算案例
- 集合实现用户登录注册案例
- opengl 绘制拉框 不用重新绘制底图的方法
- Eclipse挂载Tomcat服务器发布项目
- C# IEnumerable<T>、IEnumerator<T>、List<T>、ArrayList、[]数组各各的区别
- 框架,JavaBeans与内省(Introspector)
- Objective-C中的常用数学常量宏及函数
- JavaWeb-13 (用户的注册和登录案例)
- C语言正则表达式详解 regcomp() regexec() regfree()详解
- getOutputStream() has already been called for this response异常的原因和解决方法
- nyoj-20-吝啬的国度-DFS+容器
- 模板模式
- 串口中怎样接收一个完整数据包的解析
- 2015考研调剂
- Canvas类和Paint类 画图
- Android四种数据存储方式之一SharedPreferenced