web 学习笔记13_1-典型MVC Web工程演示
来源:互联网 发布:sql语句 修改 编辑:程序博客网 时间:2024/06/16 07:14
1、用户注册和登陆的案例:
主要是学习一个软件的架构a.技术架构:三层架构(表现层MVC:M:model V:View C:Controller)b.要求:JSP中不能出现一行java脚本或java表达式。除了指令<%@%>,其余地方不能有<%%>c.数据库:临时使用xml。解析使用Dom4j
2、基本的开发步骤:
a.建立工程,搭建开发环境(拷贝jar包、建立配置文件).b.建立类所用的包(根据3层架构模型) M:model ---javabean V:View ---JSP显示,交互 C:Controller ---Servlet控制业务逻辑 com.example.bean:放JavaBean 弄出数据库 com.example.dao:放Dao接口 com.example.dao.impl:放Dao接口的实现 com.example.servcie:业务接口 com.example.service.impl:业务接口实现 com.example.web.controller:Servlet控制器 com.example.utils ; 工具类的包c.我们先写bean包里面的类,因为它在各个层之间穿越. 建一个User.java类,最好实现Serializable接口 定义你需要的变量 使用get set 方法生成,最好生成下toString方法,便于直接输出调试。d.再编写service包里面的类:
这个包是给页面服务的,我们写的时候面向接口,便于扩展。 你页面只有登录和注册,所以我们服务层就提供2个方法,分别是登陆和注册。 例如: public interface UserService { /** * 根据用户名和密码登录 * @return 登录成功返回此用户,否则返回null */ public User login(String username,String password ) ; /** * 注册用户 * @param user 要注册的用户 * @throws UserExistsException 当用户名已经存在的时候,抛出一个用户已存在异常 */ public void register(User user) throws UserExistsException ; } 上面方法抛出了个UserExistsException异常,我们再新建一个exception,编写下UserExistsException类 com.example.exception UserExistsException.java: public class UserExistsException extends Exception { } //自己的异常定义,就是这么简单。 现在服务层接口定义好了,等会再编写impl实现类。
e.编写dao层接口
例如: com.example.dao UserDao.java: public interface UserDao { /** * 根据用户名和密码查询用户 * @return 查询到用户返回此用户,否则返回null */ public User findUserByUserNameAndPassword(String username,String password) ; /** * 注册用户 * @param user 要注册的用户 */ public void add(User user) ; /** * 根据用户的名字查找用户,看看是否已经注册 * @param name 用户的名字 * @return 查询到了返回此用户,否则返回null */ public User findUserByUserName(String name) ; } dao层的接口就定义好了,具体的impl的实现类,等会再编写。
f.编写dao接口的实现类:
现在用xml文件,以后我们可以修改这个地方来使用数据库存储。 我们使用xml解析,所以我们在utils包里面建一个工具类 com.example.utils JaxpUtils.java: 例如: //操作XML文件的方法 public class JaxpUtils { static String path ; static{ path = JaxpUtils.class.getClassLoader().getResource("users.xml").getPath() ; } public static Document getDocument(){ try {//创建一个dom4j解析器 SAXReader reader = new SAXReader() ; Document document = reader.read(path) ; return document ; } catch (DocumentException e) { e.printStackTrace(); } return null ; } public static void write2xml(Document document){ try { XMLWriter writer = new XMLWriter(new FileOutputStream(path), OutputFormat.createPrettyPrint()) ; writer.write(document) ; writer.close() ; } catch (Exception e) { e.printStackTrace(); } } } 再调用工具类,编写dao的实现类 com.example.dao.impl UserDaoImpl.java: 例如: public class UserDaoImpl implements UserDao { public User findUserByUserNameAndPassword(String username, String password) { Document document = JaxpUtils.getDocument() ;//加载Dom树 //查询需要的node节点 Node node = document.selectSingleNode("//user[@username='" + username+ "' and @password='" + password + "']") ; if(node != null){ User user = new User() ;//找到了用户,封装数据 user.setUsername(username) ; user.setPassword(password) ; user.setEmail(node.valueOf("@email")) ; String bithday = node.valueOf("@birthday") ; try { user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(bithday)) ; } catch (ParseException e) { e.printStackTrace(); } return user; } return null; } public void add(User user) { Document document = JaxpUtils.getDocument() ;//加载dom树 Element root = document.getRootElement() ;//拿到根节点 //添加一个user节点 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())) ; JaxpUtils.write2xml(document) ;//将dom树保存到硬盘上 } public User findUserByUserName(String name) { Document document = JaxpUtils.getDocument() ;//加载Dom树 //查询需要的node节点 Node node = document.selectSingleNode("//user[@username='" + name +"']") ; if(node != null){ User user = new User() ;//找到了用户,封装数据 user.setUsername(name) ; user.setPassword("@password") ; user.setEmail(node.valueOf("@email")) ; String bithday = node.valueOf("@birthday") ; try { user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(bithday)) ; } catch (ParseException e) { e.printStackTrace(); } return user; } return null; } }
g. 编写service接口的实现类:
com.example.service.impl UserServiceImpl.java 例如: public class UserServiceImpl implements UserService { UserDao dao = new UserDaoImpl() ; public User login(String username, String password) { return dao.findUserByUserNameAndPassword(username, password); } public void register(User user) throws UserExistsException {//抛一个用户存在的异常 User u = dao.findUserByUserName(user.getUsername()) ;//查找用户 if(u == null) dao.add(user) ;//说明用户没有注册过 else throw new UserExistsException() ; } } 很简单。后面我们在用户访问servlet的时候,servlet只需要调用这个服务的方法来注册和登陆了。
h.现在需要写和页面相关的内容了。
index.jsp: <body> <a href = "register.jsp">注册</a> <a href = "login.jsp">登陆</a> </body> regiest.jsp: <body> <h1>注册用户</h1> <hr> <center> <form action="${pageContext.request.contextPath }/servlet/RegisterServlet" method="post"> <table> <tr> <td align ="right">姓名:</td> <td align = "left"><input type = "text" name = "username" value = "${user.username }"></td> <td><span>${user.errors.username }</span></td> </tr> <tr> <td align ="right">密码:</td> <td align = "left"><input type = "password" name = "password" ></td> <td><span>${user.errors.password }</span></td> </tr> <tr> <td align ="right">确认密码:</td> <td align = "left"><input type = "password" name = "repassword" ></td> <td></td> </tr> <tr> <td align ="right">邮箱:</td> <td align = "left"><input type = "text" name = "email" value = "${user.email }"></td> <td><span>${user.errors.email }</span></td> </tr> <tr> <td align ="right">生日:</td> <td align = "left"><input type = "text" name = "birthday" value = "${user.birthday }"></td> <td><span>${user.errors.birthday }</span></td> </tr> <tr> <td colspan = "3" align = "center"><input type = "submit" value = "注册"></td> </tr> </table> </form> </center> </body>
i.我们需要给页面传递过来的数据写个bean类,封装数据
新建一个包com.example.web.formbean UserFormBean.java //此bean专门用来封装页面的数据,因传递过来的数据都是字符串,和User里面定义的不一样 里面的成员变量 private String username; private String password; private String repassword; private String email; private String birthday; //提供一个错误信息 private Map<String,String> errors = new HashMap<String,String>() ; 生成get set方法 我们在添加一个服务端验证的方法,防止客户端绕过JavaScript验证,直接达到服务器 例如: //服务端验证 public boolean validate(){ //验证用户名 if(username == "" || username == null){ errors.put("username", "用户名不能为空") ; }else{ if(username.length() > 8 || username.length() < 3){ errors.put("username", "用户名长度必须在3~8位之间") ; } } //验证密码 if(password == "" || password == null){ errors.put("password", "密码不能为空") ; }else{ if(password.length() > 8 || password.length() < 3){ errors.put("password", "密码长度必须在3~8位之间") ; } } if(!repassword.equals(password)){ errors.put("password", "两次密码输入不一致") ; } //验证邮箱 if(email == "" || email == null){ errors.put("email", "邮箱不能为空") ; }else{ if(!email.matches("^([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})(\\]?)$")) errors.put("email", "邮箱格式不正确") ; } //验证生日 if(birthday == "" || birthday == null){ errors.put("birthday", "生日不能为空") ; }else{ DateLocaleConverter dlc = new DateLocaleConverter() ; try { dlc.convert(birthday) ; } catch (Exception e) { errors.put("birthday", "日期格式错误") ; } } return errors.isEmpty() ;//如果是空的就说明验证通过 }
j、接下来我们可以写Servlet。
先编写一个工具类 com.example.utils WebUtils.java //专门为页面服务: 封装了页面的信息 public class WebUtils { public static <T> T fillFormBean(Class<T> clazz,HttpServletRequest request){ T t = null ; try { t = clazz.newInstance() ;//使用了个反射 BeanUtils.populate(t, request.getParameterMap()) ; } catch (Exception e) { e.printStackTrace(); } return t ; } } 再编写servlet com.example.web.servlet RegisterServlet.java /完成注册的功能 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"); PrintWriter out = response.getWriter(); //第一步,先封装数据到userbean中 UserFormBean ufb = WebUtils.fillFormBean(UserFormBean.class, request) ; //第二步,验证数据 if(ufb.validate()){ //说明验证通过 //第三步,将formbean中的数据拷贝到user对象 User user = new User() ; //由于formbean中的生日是String类型,userbaen中的生日是Date类型,beanUtils类不能自动转换,因此必须注册一个日期类型转换器 try { ConvertUtils.register(new DateLocaleConverter(), Date.class) ; BeanUtils.copyProperties(user, ufb) ; } catch (Exception e) { e.printStackTrace(); } //第四步,注册用户 //调用业务逻辑层完成注册 UserService us = new UserServiceImpl() ; try { us.register(user) ; //注册成功 //返回登陆页面 response.getWriter().write("恭喜你,注册成功,2秒后转向登陆页面") ; response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.jsp") ; //response.sendRedirect(request.getContextPath() + "/login.jsp") ; } catch (UserExistsException e) { //说明用户已经注册过了 ufb.getErrors().put("username", "此用户名已经被注册过了,请换一个") ; //将ufb存入request对象 request.setAttribute("user", ufb) ; request.getRequestDispatcher("/register.jsp").forward(request, response) ; } }else{ //验证不通过 //完成数据的回显操作,把ufb对象存放到request request.setAttribute("user", ufb) ; request.getRequestDispatcher("/register.jsp").forward(request, response) ; } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
k、编写登陆页面jsp
<body> <center> <h1>登陆页面</h1> <hr> <font color =red>${error }</font> <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post"> <table> <tr> <td align ="right">姓名:</td> <td align = "left"><input type = "text" name = "username" ></td> <td><span></span></td> </tr> <tr> <td align ="right">密码:</td> <td align = "left"><input type = "password" name = "password" ></td> <td><span></span></td> </tr> <tr> <td colspan = "3"><input type = "submit" value = "登陆"></td> </tr> </table> </form> </center> </body>
l、编写登陆的Servlet
com.example.web.servlet LoginServlet.java 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"); PrintWriter out = response.getWriter(); //获取页面的数据 String name = request.getParameter("username") ; String pass = request.getParameter("password") ; //验证数据(略) //调用service层完成业务逻辑 UserService us = new UserServiceImpl() ; User user = us.login(name, pass) ; if(user != null){ //合法用户 request.getSession().setAttribute("loginuser", user) ; request.getRequestDispatcher("/main.jsp").forward(request, response) ; }else{ //非法用户 request.getSession().setAttribute("error", "用户名或者密码错误") ; response.sendRedirect(request.getContextPath() + "/login.jsp") ; } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } 编写一个登陆成功之后的页面 main.jsp <body> ${loginuser.username },欢迎你 </body>
到这里整个流程都结束了,对整个的3层架构有了更加深入的了解了。
总结下:
3层架构,我们写dao的时候是面向接口的,有什么好处呢?
如果以后我们存储的数据方式改变了,例如想用数据库存储,不用改变其他的类,我们只要加类,重新实现下
扩展性更好了。
阅读全文
0 0
- web 学习笔记13_1-典型MVC Web工程演示
- Django学习笔记--新建web工程步骤
- Spring web MVC开发学习笔记
- Spring Web MVC 的学习笔记
- Spring Web MVC框架学习笔记
- Spring Web MVC系统学习笔记
- Java.Web学习笔记 spring MVC
- SPRING Web MVC 学习笔记--启动过程
- Spring Web MVC学习笔记目录
- Spring Web MVC系统学习笔记
- WEB前端技术_JavaScript学习_1
- WEB前端技术_JQuery学习_1
- Web MVC framework 笔记
- 学习web-新建工程
- web项目典型的工程目录结构和build.xml
- 登录工程:现代 Web 应用的典型身份验证需求
- 登录工程二:现代 Web 应用的典型身份验证需求
- sencha touch学习笔记一:web工程下的示例
- HDU 2544 dijk优化探索---优先队列优化
- 多表联查
- 向量 ——2D(如何判断一个向量在另外一个向量的哪一侧)
- 详解线上线下收单业务(2)
- MySQL存储过程
- web 学习笔记13_1-典型MVC Web工程演示
- java引用类型和基本类型的比较
- Mac 安装mysql数据库后如何初始化root密码
- PAT (Advanced Level) Practise 1041 Be Unique (20)
- 旋转数组的最小数字
- 算法设计与分析复习(一):习题解答
- [LeetCode] Max Points on a Line
- 详解线上线下收单业务(1)
- 尺取法