5.会话技术 5.1Cookie技术 5.1.1服务器把用户数据以Cookie技术写到各自的浏览器。 当用户再去访问访问浏览器的时候,比如登录名、密码等就是cookie 5.1.1.1浏览器-Http请求-服务器-创建cookie.java-服务器-浏览器-浏览器存放cookie的地方(就是缓存)。 5.1.1.2如何制造和保存cookie呢? 写MakeCookie.java-http://localhost:8080/wdfgdzx/MakeCookie-访问后IE里就有缓存文件了。wdfgdzx/-内容:name wdfgdzxlocalhost/wdfgdzx/1536383491993630695784219903830430695776* 5.1.1.3如何读取cookie呢? 写一个ReadCookie.java-http://localhost:8080/wdfgdzx/ReadCookie-这个带的cookie只会带wdfgdzx这个web应用下的cookie。 接受端就可以根据需求来获取cookie了。 A.产生cookie package cookie; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import service.UserService; public class MakeCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //创建cookie,看帮助文档 Cookie myCookie=new Cookie("name","wdfgdzx"); myCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(myCookie); } } B.读取cookie package cookie; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import service.UserService; public class ReadCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //读取cookie所有信息,再选中你要的信息 Cookie cookie[]=req.getCookies(); System.err.println(cookie.length); //遍历cookie for(int i=0;i<cookie.length;i++){ Cookie myCookie=cookie[i]; resp.getWriter().println("名字"+myCookie.getName()+"值"+myCookie.getValue()); } } } 5.1.2实际应用 5.1.2.1cookie的小总结知识点。 A.cookie可以简单理解为一张表,一列是name,一列是value B.cookie是在服务端创建,保存在浏览器端的 C.cookie的生命周期,可以通过myCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期设置/不设置当关闭浏览器就会导致cookie失效。 D.如果cookie的名字相同,但是值不同,会发生什么。第二个会替换第一个cookie的值。 E.一个站点可以保存多个cookie,但是不要超过20个cookie/ F.cookie是以明文方式存放的,安全性较低,我们可以通过加密后保存。—>引出MD5算法。以后我们的密码都要使用加密存放,在验证密码 的时候,对用户输入的密码进行MD5加密然后再到数据库去验证。 5.1.2.2应用案例欢迎你登录,上传时间是多少的案例 A.完整案例代码 package cookie; import java.io.IOException; import java.text.SimpleDateFormat; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import service.UserService; public class ReadCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //读取cookie所有信息,再选中你要的信息 if(req.getCookies()!=null){//保证有cookie才去遍历没有就提示下 boolean flag=false; Cookie cookie[]=req.getCookies(); //System.err.println(cookie.length); //遍历cookie,计入上次登录时lastTime for(Cookie myCookie:cookie){ if("lastTime".equals(myCookie.getName())){ resp.getWriter().println("你上次登录时间是"+myCookie.getValue()); //更新时间 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); flag=true; break; } } if(!flag){ resp.getWriter().println("你是第一次登录!"); //把当前日期保存到cookie中 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); } }else{ resp.getWriter().println("没有找到相关缓存!请先访问http://localhost:8080/wdfgdzx/MakeCookie"); } } } B.修正主案例的管理页面展示 package view; import java.io.IOException; import java.text.SimpleDateFormat; import javax.servlet.ServletException; import javax.servlet.http.*; public class Admin extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); if(req.getCookies()!=null){//保证有cookie才去遍历没有就提示下 boolean flag=false; Cookie cookie[]=req.getCookies(); //System.err.println(cookie.length); //遍历cookie,计入上次登录时lastTime for(Cookie myCookie:cookie){ if("lastTime".equals(myCookie.getName())){ //resp.getWriter().println("你上次登录时间是"+myCookie.getValue()); resp.getWriter().println("<img src='Image/3.png'>"+"欢迎您首长同志:"+req.getParameter("username") +"您上次登录时间是"+myCookie.getValue() +"  <a href='/wdfgdzx/Login'>返回登录界面</a>"+"<hr/>"); resp.getWriter().println("<h3>请选择操作</h3>"); resp.getWriter().println("<a href='/wdfgdzx/AdminUser'>管理用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goAddView'>添加用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goSelect'>查找用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/Login'>退出系统</a><br/>"); resp.getWriter().println("<hr/><img src='Image/4.png'>"); //更新时间 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); flag=true; break; } } if(!flag){ //resp.getWriter().println("你是第一次登录!"); resp.getWriter().println("<img src='Image/3.png'>"+"欢迎您首长同志:"+req.getParameter("username") +"您是第一次登录!" +"  <a href='/wdfgdzx/Login'>返回登录界面</a>"+"<hr/>"); resp.getWriter().println("<h3>请选择操作</h3>"); resp.getWriter().println("<a href='/wdfgdzx/AdminUser'>管理用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goAddView'>添加用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goSelect'>查找用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/Login'>退出系统</a><br/>"); resp.getWriter().println("<hr/><img src='Image/4.png'>"); //把当前日期保存到cookie中 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); } }else{ resp.getWriter().println("没有找到相关缓存!请先访问http://localhost:8080/wdfgdzx/MakeCookie"); } } } 5.1.2.3应用案例二,记住密码。 A.登录界面代码 package view; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; public class Login extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //从cookie中选择中keep的cookie String username=""; if(req.getCookies()!=null){ Cookie cookies[]=req.getCookies(); for(Cookie keepCookie:cookies){ if(keepCookie.getName().equals("username")){ username=keepCookie.getValue(); } } } //返回一个界面 resp.getWriter().println("<img src='Image/3.png'><hr/>"); resp.getWriter().println("<h1>用户登录</h1>"); resp.getWriter().println("<form action='/wdfgdzx/Controller' method='post'>"); resp.getWriter().println("用户名称:<input type='text' name='username'value='"+username+"'/><br/>"); resp.getWriter().println("用户密码:<input type='password' name='password'/><br/>"); resp.getWriter().println("<input type='checkbox' name='keep' value='keep'/>在此电脑上保留用户名<br/>"); resp.getWriter().println("<input type='submit' value='登录'/><br/>"); resp.getWriter().println("</form>"); if(req.getAttribute("err")!=null){ resp.getWriter().println("<font color='red'>"+req.getAttribute("err").toString()+"</font>"); } resp.getWriter().println("<hr/><img src='Image/4.png'>"); } } B.控制层加入了cookie package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import service.UserService; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //到数据库验证用户名和密码servlet本身也是java类,因此其操作数据库和普通的java类是一样的 String username=req.getParameter("username"); String password=req.getParameter("password"); //判断用户是否希望保留用户名 String isKeep=req.getParameter("keep"); if(isKeep!=null&&isKeep.equals("keep")){ //要保存用户名 //创建cookie并保存到登录用户的机器上两周 Cookie nameCookie=new Cookie("username",username); nameCookie.setMaxAge(7*2*24*3600); //回写 resp.addCookie(nameCookie); } //创建UserService对象,完成到数据库的验证 UserService userService=new UserService(); User user=new User(); user.setUsername(username); user.setPassword(password); if(userService.checkUser(user)) { String info=java.net.URLEncoder.encode(req.getParameter("username"),"UTF-8");//urlEncode编码如果需要转向的化 req.getRequestDispatcher("/Admin?username="+info).forward(req, resp); }else{ req.setAttribute("err", "用户名或者密码错误"); req.getRequestDispatcher("/Login").forward(req, resp); } } } 5.1.2.4浏览过的商品展示案例 A.用户最近浏览的信息,最后浏览的放在最前面。 B.自己作为作业考虑实现。 5.1.3cookie的细节讨论 5.1.3.1一个浏览器最多放300个cookie,一个站点最多存放20个cookie,而且cookie大小是限制在4K的。 5.1.3.2cookie默认生命周期是会话级别的,通过setMaxAge可以设置生命周期,如果设置的是正数,就代表正数秒后cookie就失效了。 如果是0代表要删除此cookie,保存哪里的else就可以置空了,当然也需要resp.addCookie(nameCookie);一定带上否则不起作用。/ 如果是负数,相当于该cookie生命周期是会话级别的。 5.1.3.3如果设置的value是汉字,会报错 Control character in cookie value, consider BASE64 encoding your value怎么办?用下面的 编码和解码。 A.存放的时候编码 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import service.UserService; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //到数据库验证用户名和密码servlet本身也是java类,因此其操作数据库和普通的java类是一样的 String username=req.getParameter("username"); String password=req.getParameter("password"); //判断用户是否希望保留用户名 String isKeep=req.getParameter("keep"); if(isKeep!=null&&isKeep.equals("keep")){ //要保存用户名 //创建cookie并保存到登录用户的机器上两周 String tempName=java.net.URLEncoder.encode(username, "utf-8"); Cookie nameCookie=new Cookie("username",tempName); nameCookie.setMaxAge(7*2*24*3600); //回写 resp.addCookie(nameCookie); } //创建UserService对象,完成到数据库的验证 UserService userService=new UserService(); User user=new User(); user.setUsername(username); user.setPassword(password); if(userService.checkUser(user)) { String info=java.net.URLEncoder.encode(req.getParameter("username"),"UTF-8");//urlEncode编码如果需要转向的化 req.getRequestDispatcher("/Admin?username="+info).forward(req, resp); }else{ req.setAttribute("err", "用户名或者密码错误"); req.getRequestDispatcher("/Login").forward(req, resp); } } } B.取出的时候解码 package view; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; public class Login extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //从cookie中选择中keep的cookie String username=""; if(req.getCookies()!=null){ Cookie cookies[]=req.getCookies(); for(Cookie keepCookie:cookies){ if(keepCookie.getName().equals("username")){ //对有中文的cookie进行解码 String tempName=java.net.URLDecoder.decode(keepCookie.getValue(), "utf-8"); username=tempName; } } } //返回一个界面 resp.getWriter().println("<img src='Image/3.png'><hr/>"); resp.getWriter().println("<h1>用户登录</h1>"); resp.getWriter().println("<form action='/wdfgdzx/Controller' method='post'>"); resp.getWriter().println("用户名称:<input type='text' name='username'value='"+username+"'/><br/>"); resp.getWriter().println("用户密码:<input type='password' name='password'/><br/>"); resp.getWriter().println("<input type='checkbox' name='keep' value='keep'/>在此电脑上保留用户名<br/>"); resp.getWriter().println("<input type='submit' value='登录'/><br/>"); resp.getWriter().println("</form>"); if(req.getAttribute("err")!=null){ resp.getWriter().println("<font color='red'>"+req.getAttribute("err").toString()+"</font>"); } resp.getWriter().println("<hr/><img src='Image/4.png'>"); } } 5.2session 5.2.1什么是会话? 5.2.1.1用户打开一个浏览器访问某个网站,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为“一个会话”。比如打电话。 5.2.1.2会话解决了那些问题?不同的用户,各自定义自己的头像。怎么展示呢?服务器要想办法为每个用户保存这些数据。request肯定不行,所以要用会话保存这些数据。保存会话的技术有session和cookie 5.2.1.3抛砖引玉,为什么需要cookie技术呢? 登录网站的时候,不同的用户都能看到自己上次登录的时间。/浏览过的商品,再次展示,也是数据库记录就行了,没有登录也可以看到怎么是现实呢???就是如果现实用户浏览器历史/突然想到用户头像也可以记录了。/如何记住用户名工能?下次登录不需要重新输入。 5.2.1.4解决方法:就是我们万能的cookie技术。 5.2.2抛砖引玉 5.2.2.1不同的用户,各自定义自己的头像。不同用户淘宝购物车里的商品不一样怎么办。不同用户登录显示不同的名字。 5.2.2.2解决之道就是session/它是保存在服务器端的 5.2.3Session讲解 5.2.3.1工作原理 A.浏览器—服务器—服务端创建session(第一次访问session的时候),也可以理解为一个表name(String)列,value(object)列 —session是给此浏览器独享的—所以再打开一个浏览器就会再创建一个session(独享的)—同一个浏览器在web服务器内存中的session 是可以给所有的servlet共享的(卧槽,可怕又牛逼哈哈)—生命周期默认是30分钟,也可以修改。 B.创建代码 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; public class MakeSession extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //访问session,当发现没有session的时候,会自动创建一个session HttpSession httpSession=req.getSession(); //给该session放入属性 httpSession.setAttribute("name", "wdfgdzxHttpSesson"); httpSession.setAttribute("age", "36"); resp.getWriter().println("创建session并放置属性成功!"); } } C.取出代码/说明同一个浏览器在web服务器内存中的session是可以给所有的servlet共享的(卧槽,可怕又牛逼哈哈) package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; public class ReadSession extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //获取session HttpSession mySession=req.getSession(); //因为返回的是对象,所以需要转下 String name=(String) mySession.getAttribute("name"); if(name!=null){ resp.getWriter().println("session中取出的name:"+name); }else{ resp.getWriter().println("session没有此属性"); } } } 5.2.4Session知识再补充 5.2.4.1如何浏览器向session设置属性的时候,名字相同了会出现说明情况?/也是会替换第一个设置的属性值。 5.2.4.2如何删除session中的属性?mySession.removeAttribute("name");/使用这个方法删除即可 5.2.4.3也可以放置对象属性 A.放置代码 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class MakeSession extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //访问session,当发现没有session的时候,会自动创建一个session HttpSession httpSession=req.getSession(); //给该session放入属性 httpSession.setAttribute("name", "wdfgdzxHttpSesson"); //httpSession.setAttribute("name", "repeatName"); httpSession.setAttribute("age", "36"); //创建对象 User user=new User(); user.setUsername("对象的名称"); httpSession.setAttribute("user", user); resp.getWriter().println("创建session并放置属性成功!"); } } B.取出代码 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class ReadSession extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //获取session HttpSession mySession=req.getSession(); //因为返回的是对象,所以需要转下 //mySession.removeAttribute("name"); String name=(String) mySession.getAttribute("name"); User user=(User) mySession.getAttribute("user"); if(name!=null){ resp.getWriter().println("session中取出的name:"+name); resp.getWriter().println("session中取出的对象:"+user.toString()); }else{ resp.getWriter().println("session没有此属性"); } } } C.小结:session是存在服务器的内存中的/一个浏览器独享session对象/默认生命周期是30分钟,可以通过tomcat的web.xml修改,也可以通过工程的web.xml修改。如果对实时性操作高,可以设置//httpSession.setMaxInactiveInterval(3600);这句话就要求必须在1分钟内去取session,否则将会访问不到,在一分钟内访问会重新计时/session中可以存放多个属性/session中可以存放对象。/如果session中属性名称重复了则会替换第一个属性值。/清除session函数session.invalidate();通常用于安全退出。所有属性失效/移除某一个属性httpSession.removeAttribute("name"); 5.2.5Session实际案例 5.2.5.1如何防止直接输入地址就可以访问?先防止一个Admin页面 A.先写入session package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import pojo.User; import service.UserService; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //到数据库验证用户名和密码servlet本身也是java类,因此其操作数据库和普通的java类是一样的 String username=req.getParameter("username"); String password=req.getParameter("password"); //判断用户是否希望保留用户名 String isKeep=req.getParameter("keep"); if(isKeep!=null&&isKeep.equals("keep")){ //要保存用户名 //创建cookie并保存到登录用户的机器上两周 String tempName=java.net.URLEncoder.encode(username, "utf-8"); Cookie nameCookie=new Cookie("username",tempName); nameCookie.setMaxAge(7*2*24*3600); //回写 resp.addCookie(nameCookie); } //创建UserService对象,完成到数据库的验证 UserService userService=new UserService(); User user=new User(); user.setUsername(username); user.setPassword(password); if(userService.checkUser(user)) { //把user对象保存到session中 HttpSession httpSession=req.getSession(); httpSession.setAttribute("user", user); String info=java.net.URLEncoder.encode(req.getParameter("username"),"UTF-8");//urlEncode编码如果需要转向的化 req.getRequestDispatcher("/Admin?username="+info).forward(req, resp); }else{ req.setAttribute("err", "用户名或者密码错误"); req.getRequestDispatcher("/Login").forward(req, resp); } } } B.Admin界面 package view; import java.io.IOException; import java.text.SimpleDateFormat; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class Admin extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //取出user信息判断是否为空 User user=(User) req.getSession().getAttribute("user"); if(user==null){ req.setAttribute("err", "请先登录网站!"); req.getRequestDispatcher("/Login").forward(req, resp); return;//这里一定记得return } if(req.getCookies()!=null){//保证有cookie才去遍历没有就提示下 boolean flag=false; Cookie cookie[]=req.getCookies(); //System.err.println(cookie.length); //遍历cookie,计入上次登录时lastTime for(Cookie myCookie:cookie){ if("lastTime".equals(myCookie.getName())){ //resp.getWriter().println("你上次登录时间是"+myCookie.getValue()); resp.getWriter().println("<img src='Image/3.png'>"+"欢迎您首长同志:"+req.getParameter("username") +"您上次登录时间是"+myCookie.getValue() +"  <a href='/wdfgdzx/Login'>返回登录界面</a>"+"<hr/>"); resp.getWriter().println("<h3>请选择操作</h3>"); resp.getWriter().println("<a href='/wdfgdzx/AdminUser'>管理用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goAddView'>添加用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goSelect'>查找用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/Login'>退出系统</a><br/>"); resp.getWriter().println("<hr/><img src='Image/4.png'>"); //更新时间 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); flag=true; break; } } if(!flag){ //resp.getWriter().println("你是第一次登录!"); resp.getWriter().println("<img src='Image/3.png'>"+"欢迎您首长同志:"+req.getParameter("username") +"您是第一次登录!" +"  <a href='/wdfgdzx/Login'>返回登录界面</a>"+"<hr/>"); resp.getWriter().println("<h3>请选择操作</h3>"); resp.getWriter().println("<a href='/wdfgdzx/AdminUser'>管理用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goAddView'>添加用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/MyController?type=goSelect'>查找用户</a><br/>"); resp.getWriter().println("<a href='/wdfgdzx/Login'>退出系统</a><br/>"); resp.getWriter().println("<hr/><img src='Image/4.png'>"); //把当前日期保存到cookie中 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String myTime=simpleDateFormat.format(new java.util.Date()); Cookie timeCookie=new Cookie("lastTime",myTime); timeCookie.setMaxAge(3600);//3600秒,设置cookie的生命周期 //把创建的cookie会写给浏览器。 resp.addCookie(timeCookie); } }else{ resp.getWriter().println("没有找到相关缓存!请先访问http://localhost:8080/wdfgdzx/MakeCookie"); } } } 5.2.5.2这么多页面,都去这么写代码验证不是很麻烦?所以引出了过滤器! 5.2.5.3session为什么不同的浏览器,就能是被去创建一个独享的session呢,服务器如何实现的? A.浏览器A访问-服务器创建一个session—返回到浏览器A端Cookie:username=zhugeliang; JSESSIONID=1FFFC84988559D54FA645377FE93C8 所以下次访问,根据id取到这个session就能带出来。—浏览器B来了—还是会服务器先创建—重复上面的步骤。这就是服务器能为不同的 浏览器提供不同的session的原理。 5.2.5.4验证码案例使用 A.原理是使用到java的绘图技术。 B.首先看绘图+随机数差生的代码 package view; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.*; public class MakeCode extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //6禁止缓存随机图片 resp.setDateHeader("Expires", -1); resp.setHeader("Cache-Control", "no-cache"); resp.setHeader("Pargam","no-cache"); //7通知客户机以图片的方式打开发送过去的数据 resp.setHeader("Content-Type", "image/jpeg"); //1在内存中创建衣服图片 BufferedImage bufferedImage=new BufferedImage(70,22,BufferedImage.TYPE_INT_RGB); //2向图片上写数据 Graphics graphics=bufferedImage.getGraphics(); //3设置背景色 graphics.setColor(Color.pink); graphics.fillRect(0, 0, 70, 22); //设置写入数据的颜色和字体 graphics.setColor(Color.black); graphics.setFont(new Font(null, Font.BOLD, 20)); //4向图片写数据 String temp=makeRandom();//temp如果是汉字或者是一个数学题库都可以生成的 //随机产生的值保存到session req.getSession().setAttribute("verifyCode", temp); graphics.drawString(temp, 0, 20); //5把写好的图片数据给浏览器 ImageIO.write(bufferedImage, "jpg", resp.getOutputStream()); } //产生7位随机数 public String makeRandom(){ Random random=new Random(); //明显9999999和7控制了 到底产生几位数 String temp=random.nextInt(999999)+""; StringBuffer sringBuffer=new StringBuffer(); for(int i=0;i<6-temp.length();i++){//为什么随机数不够7位补充0用的 sringBuffer.append("0"); } temp=temp+sringBuffer.toString(); return temp; } } C.登录界面代码 package view; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; public class Login extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //从cookie中选择中keep的cookie String username=""; if(req.getCookies()!=null){ Cookie cookies[]=req.getCookies(); for(Cookie keepCookie:cookies){ if(keepCookie.getName().equals("username")){ //对有中文的cookie进行解码 String tempName=java.net.URLDecoder.decode(keepCookie.getValue(), "utf-8"); username=tempName; } } } //返回一个界面 resp.getWriter().println("<img src='Image/3.png'><hr/>"); resp.getWriter().println("<h1>用户登录</h1>"); resp.getWriter().println("<form action='/wdfgdzx/Controller' method='post'>"); resp.getWriter().println("用户名称:<input type='text' name='username' value='"+username+"'/><br/>"); resp.getWriter().println("用户密码:<input type='password' name='password'/><br/>"); //这里回写图片本质还是文件 resp.getWriter().println("验证码 :<input type='text' name='verifyCode' value=''/>" + "<img src='/wdfgdzx/MakeCode' /><br/>"); resp.getWriter().println("<input type='checkbox' name='keep' value='keep'/>在此电脑上保留用户名<br/>"); resp.getWriter().println("<input type='submit' value='登录'/><br/>"); resp.getWriter().println("</form>"); if(req.getAttribute("err")!=null){ resp.getWriter().println("<font color='red'>"+req.getAttribute("err").toString()+"</font>"); } resp.getWriter().println("<hr/><img src='Image/4.png'>"); } } D.控制器代码 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import pojo.User; import service.UserService; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //到数据库验证用户名和密码servlet本身也是java类,因此其操作数据库和普通的java类是一样的 String username=req.getParameter("username"); String password=req.getParameter("password"); //还要获取用户输入的验证码,这个是首次验证的,不对就不到数据库去 String verifyCode=req.getParameter("verifyCode"); String sessionVerifyCode=(String) req.getSession().getAttribute("verifyCode"); boolean flag=false; if(verifyCode.equals(sessionVerifyCode)){ //验证ok flag=true;//继续执行 }else{ req.setAttribute("err", "验证码错误"); req.getRequestDispatcher("/Login").forward(req, resp); return;//这个及时返回 } //判断用户是否希望保留用户名 String isKeep=req.getParameter("keep"); if(isKeep!=null&&isKeep.equals("keep")){ //要保存用户名 //创建cookie并保存到登录用户的机器上两周 String tempName=java.net.URLEncoder.encode(username, "utf-8"); Cookie nameCookie=new Cookie("username",tempName); nameCookie.setMaxAge(7*2*24*3600); //回写 resp.addCookie(nameCookie); } //创建UserService对象,完成到数据库的验证 UserService userService=new UserService(); User user=new User(); user.setUsername(username); user.setPassword(password); if(userService.checkUser(user)&&flag==true) { //把user对象保存到session中 HttpSession httpSession=req.getSession(); httpSession.setAttribute("user", user); String info=java.net.URLEncoder.encode(req.getParameter("username"),"UTF-8");//urlEncode编码如果需要转向的化 req.getRequestDispatcher("/Admin?username="+info).forward(req, resp); }else{ req.setAttribute("err", "用户名或者密码错误"); req.getRequestDispatcher("/Login").forward(req, resp); } } } E.总结:这里最重要的就是生成验证码的servlet,代码重点看下。 5.2.6关闭IE后再打开IE还能访问到session 5.2.6.1如果把浏览器关闭了,session在服务器端是否还在?答案是:存在的。如果session生命周期是30min,该session不会随着浏览器的 关闭而自动销毁(当然额外销毁或者再次创建肯定就没有了)。而会到30分钟后才会服务器销毁。 5.2.6.2创建session代码 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class SessionAndCookie extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //创建一个session并放入一个属性 HttpSession httpSession=req.getSession(); httpSession.setAttribute("myName", "liu19911009"); //默认30分钟 resp.getWriter().println("创建成功!"); } } 5.2.6.3获取代码 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class ReadSession extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //读取session属性 String myName=(String) req.getSession().getAttribute("myName"); resp.getWriter().println(myName); } } 5.2.6.4关闭浏览器,直接去读(同一个浏览器哈),发现也是null怎么办呢???—把session的id以cookie的方式保存即可。 A.写入session顺便放到cookie里 package session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import pojo.User; public class SessionAndCookie extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //创建一个session并放入一个属性 HttpSession httpSession=req.getSession(); httpSession.setAttribute("myName", "liu19911009"); //默认30分钟,同时把该session的id保存到cookie中 Cookie myCookie=new Cookie("JSESSIONID",httpSession.getId());//这里一定按照浏览器的来不要乱写,区分大小写的 myCookie.setMaxAge(120*60);//设置生命周期为两个小时 resp.addCookie(myCookie); resp.getWriter().println("创建成功!"); } } B.这次我们再关闭浏览器,直接访问http://localhost:8080/wdfgdzx/ReadSession发现可以访问到/不再是null了/可以的很厉害! 5.2.6.5如果用户禁止使用缓存了怎么办呢? A.URL重写/放到购物车那个项目再讲 5.2.7购物车功能(深入理解session) 5.2.7.1框架规划 A.购买书界面.java—购买数控制器.java—显示购物车的商品.java B.界面三个书—session放入值—跳转到购物车/遇到的问题是只能买一本书?怎么办呢? C.session也可以添加集合。添加集合后就可以放多本书了。—但是发现还是一本书,为什么呢?因为每次都更新了tempList;所以想办法控制住tempList不要每次都new ArrayList() D.具体控制代码 package controller; import java.io.IOException; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class BuyController extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } //ArrayList tempList=new ArrayList();还有一种方法 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); //接受用户购买书的名字 String bookName=req.getParameter("bookName"); HttpSession buySession=req.getSession(); ArrayList tempList=(ArrayList) req.getSession().getAttribute("tempList"); if(tempList==null){//判断是否为空,不是第一次购物就不会new了。这就是第二种方法 tempList=new ArrayList(); tempList.add(bookName); buySession.setAttribute("tempList", tempList); }else{ tempList.add(bookName); //更新进去 buySession.setAttribute("tempList", tempList); } //跳转到成功页面 req.getRequestDispatcher("/MyBuy").forward(req, resp); } } 5.2.7.2进一步优化,可以购买多本了,但是同样的数不显示在一起?? A.考虑到用对象添加(对象有数量属性。),但是arraylist就不行了,要用hashmap了/hashMap和arrayList的区别就是,有key值, 可以使用getBookById方法,arrayList也可以就是需要遍历太慢了,这里考虑到抽奖项目可以优化的。 B.购买的书籍排列乱序怎么办呢?只需要该一个hashMap=new LinkedHashMap();完美解决。 C.自己完善下功能,加点价格什么的。顺带把总价格算出来。 5.2.7.3实例分析总结: A.当用户点击购买的时候我们把商品保存到session中,session的结构是name 值/bookHashMap hashMap值。 hashMap的结构是key 值/ 书号 书对象。具体实现参考上面案例。 B.使用到知识点:java基础的集合arrayList、hashmap、LinkedHashMap(有序的)/session/servlet跳转技术/单态(构建模拟数据库的时候)/如何选择不同的集合。 C.List集合是有序的,Map集合默认是无序的/ List和Map都可以放null/ List可以放入相同的对象,Map也可以放相同对象,但是key值不能重复,重复只会存一个进去。 5.2.7.4用户禁用cookie后的session处理??? A.解决方案:URL地址重写。 package view; import java.io.IOException; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import pojo.Book; import simulatedDataBase.DataBase; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class ShowBook extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); out.println("<h1>欢迎光临书店</h1>"); //取出db,模拟数据库的 HashMap myDataBase=DataBase.getDataBase(); Iterator iterator=myDataBase.keySet().iterator(); //访问下session req.getSession(); while(iterator.hasNext()){ String key=(String) iterator.next(); Book book=(Book) myDataBase.get(key); String url=resp.encodeURL("/buy/BuyController?id="+book.getId()); //我希望超链接的格式 href="/buy/BuyController?id="+book.getId()+"&JSESSIONID=11223344JJ" out.println(""+book.getName()+"<a href='"+url+"'>" + "点击购买</a><br/>"); } /*out.println("三国演义<a href='/buy/BuyController?id=1&bookName=sg'>点击购买</a><br/>"); out.println("东周列国<a href='/buy/BuyController?id=2&bookName=dz'>点击购买</a><br/>"); out.println("隋唐演义<a href='/buy/BuyController?id=3&bookName=st'>点击购买</a><br/>");*/ } } B.访问源码发现出现了session了。 sg<a href='/buy/BuyController;jsessionid=E0D49E7C0557FB9C087027FFA4E65378?id=1'>点击购买</a><br/> //这里也需要url地址重写 String url=resp.encodeURL("/buy/ShowBook") ; out.println("<a href='"+url+"'>返回大厅继续购买</a>"); C.然后就可以正常使用了。 5.2.8 cookie和session对比 5.2.8.1存在的位置。cookie存在客户端的临时文件夹,session存在服务器的内存中,一个session域对象为一个用户浏览器服务。 5.2.8.2安全性来看。cookie以明文方式存在客户端的,安全性相对弱。可以通过加密后再存放md5加密。session是存放在服务器的内存中 ,所以安全性相对较强。 5.2.8.3网络传输量。cookie会传递信息给服务器,session的属性不会给客户端。 5.2.8.4生命周期。cookie的生命周期是累计的。session的信息是间隔的,比如30分钟,20分钟操作一次会重新计时。失效就是无法取出 session的属性了。以下情况session也会失效:关闭服务器/时间到/session.invalidate(); 5.2.8.5从访问范围来看。cookie为多个用户浏览器共享。session为一个用户浏览器独享,session会占用服务器内存。因此不要向session中放过多的对象。 6.网站计数器 6.1ServletContext的使用 6.1.1抛转引玉 6.1.1.1需求 A.为什么需要ServletContext?/它是一个接口/ B.你是第几位访问者?网站展示。 C.访问网站的时候回展示在线用户有多少人。 D.解决之道就是ServletContext 6.1.2什么是ServletContext 6.1.2.1说明 A.web容器在启动时,它为每个web应用程序都创建了一个对应的ServletContext对象,它代表当前web应用。 B.ServletContext对象可以通过ServletConfig.getServletContext方法引用/this.getServletContext方法。 C.ServletContext是在服务器创建的 D.ServletContext是被所有客户端共享的 E.ServletContext当WEB应用启用时候自动创建,当WEB应用关闭/或者tomcat关闭的时候自动消亡。会造成ServletContext销毁。 6.1.3快速入门案例 6.1.3.1简单理解servletContext A.servletContext也可以简单理解成一张表,和session很相似,显示name列String类型。还有一个value列Object类型。它是跨机器的, 不管谁访问,都是存在的。 6.1.3.2属性放入代码 package context; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class MakeServletContext extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //获取servletContext的对象引用 //1.通过this对象获取 ServletContext servletContext=this.getServletContext(); //2.通过servletConfig对象获取 ServletContext servletContextTwo=this.getServletConfig().getServletContext(); servletContext.setAttribute("name", "servletContextHIT"); resp.getWriter().println("属性加入成功!"); } } 6.1.3.3属性读取对象 package context; import java.io.IOException; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class ReadServletContext extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); //取出servletContext的某个属性 //获取servletContext ServletContext servletContext=this.getServletContext(); //取出属性,属性对应什么类型就转成什么类型。 String servletContextName=(String) servletContext.getAttribute("name"); out.println(servletContextName); } } 6.1.3.4WEB.XML代码 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>MakeServletContext</servlet-name> <servlet-class>context.MakeServletContext</servlet-class> </servlet> <servlet-mapping> <servlet-name>MakeServletContext</servlet-name> <url-pattern>/MakeServletContext</url-pattern> </servlet-mapping> <servlet> <servlet-name>ReadServletContext</servlet-name> <servlet-class>context.ReadServletContext</servlet-class> </servlet> <servlet-mapping> <servlet-name>ReadServletContext</servlet-name> <url-pattern>/ReadServletContext</url-pattern> </servlet-mapping> </web-app> 6.1.3.5简单聊天室的实现 6.1.3.6再总结 A.servletContext.removeAttribute("name");用于删除属性,删除后再去读取属性,值就是null了。 B.获取servletContext有两种方法。主要是tihs.getServletContext()。 C.添加属性就是servletContext.setAttribute("name", "servletContextHIT");/取出属性String servletContextName=(String) servletContext.getAttribute("name"); 6.1.4ServletContext的应用 6.1.4.1多个servlet通过servletContext实现数据共享 6.1.4.2获取web应用的初始化参数。 A.<!-- 如果希望所有的servlet都可以访问该配置,则可以这么做 --> <context-param> <param-name>name</param-name> <param-value>wdfgdzx</param-value> </context-param> B.如何获取 //这个是获取全部的哦getServletContext String initParameter=this.getServletContext().getInitParameter("name"); resp.getWriter().println(initParameter); C.实现转发跳转到下一个页面 //转发目前有的方法//resp.sendRedirect();//req.getRequestDispatcher("/").forward(req, resp); 小结下这两种方法:一个sendRedirect跳转是发生在浏览器客户端的,另一个是发生在服务器的。/希望下个页面可以使用上个页面 传递过来的属性request.setAttibute("name","value")值则应该使用req.getRequestDispatcher("/").forward(req, resp);/如果是session 传递过来的值,都可以使用,还是推荐使用req.getRequestDispatcher("/").forward(req, resp);/如果希望跳转本web应用外的应用,只 能使用第一个了resp.sendRedirect();/ servletContext也可以实现,this.getServletContext().getRequestDispatcher("/").forward(req, resp);/这种方法和第二种req.getRequestDispatcher("/").forward(req, resp);是一样的,只是知道下就可以了。 6.1.4.3利用servletContext读取资源文件properties A.db.properties文件放在webapp下和index.jsp同位置,内容username=root password=123456 B.读取代码 package context; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class FileServletContext extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); //先读取到此文件 InputStream inputStream=this.getServletContext().getResourceAsStream("db.properties"); Properties properties=new Properties(); properties.load(inputStream); out.println("username="+properties.getProperty("username")+properties.getProperty("password")); } } C.这样就轻松的读取到了资源属性了。 6.1.4.4得到文件的全路径怎么办呢? A.读取代码 package context; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class FileServletContext extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); //先读取到此文件 InputStream inputStream=this.getServletContext().getResourceAsStream("db.properties"); Properties properties=new Properties(); properties.load(inputStream); out.println("username="+properties.getProperty("username")+properties.getProperty("password")); //如何读取到一个文件的全路径 String path=this.getServletContext().getRealPath("db.properties"); out.println("路径="+path); //路径=C:UsersHIITworkspace.metadata.pluginsorg.eclipse.wst.server.core mp1wtpwebappsContextdb.properties //说明读取的是tomcat的绝对路径。不是在本地磁盘的 } } B.如果文件放在src目录下,应该使用类加载器来读取 FileServletContext.class.getClassLoader().getResourceAsStream("文件");返回的也是InputStream 6.1.5总结 A.总之,涉及到用户共享/数据量不大/不想写数据库/我们就可以考虑使用servletContext来实现了 6.3网站计数器 6.3.1如何计数(有效点击!) 6.3.1.1只要访问一次就算一次,刷新也算。。。 6.3.1.2不同的ip访问该网页,算一次有效点击,不管1天内点多少次都算一次。 6.3.1.3用户退出网站,再访问也算一次。 6.3.2方案选择 6.3.2.1目前使用方案:数据库一张表存读/静态变量存读/servletContext存读 6.3.2.2简单实现可以的,如何防止用户刷新呢。如何防表单提交。/简单解决//req.getRequestDispatcher("/Admin").forward(req, resp); /resp.sendRedirect("/Context/Admin"); 6.3.2.3登录代码 package view; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Login extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //返回一个界面 resp.getWriter().println("<h1>用户登录</h1>"); resp.getWriter().println("<form action='/Context/Controller' method='post'>"); resp.getWriter().println("用户名称:<input type='text' name='username'/><br/>"); resp.getWriter().println("用户密码:<input type='password' name='password'/><br/>"); resp.getWriter().println("<input type='submit' value='登录'/><br/>"); resp.getWriter().println("</form>"); } } 6.3.2.4控制代码 package controller; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Controller extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); String username=req.getParameter("username"); String password=req.getParameter("password"); if(username.equals("liu19911009")&&password.equals("s5012280")){ //合法 //向servletContext添加一个属性 //先取,再加,再放 String temp=(String) this.getServletContext().getAttribute("LoginNum"); if(temp==null){ this.getServletContext().setAttribute("LoginNum", "1"); }else{ //如果有+1 int tempInt=Integer.parseInt(temp)+1; this.getServletContext().setAttribute("LoginNum", tempInt+"");//这里设置成字符类型 } //req.getRequestDispatcher("/Admin").forward(req, resp); resp.sendRedirect("/Context/Admin"); }else{ //非法 } } } 6.3.2.5界面代码 package view; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Admin extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out=resp.getWriter(); out.println("<h1>管理页面</h1>"); String LoginNum=(String) this.getServletContext().getAttribute("LoginNum"); out.println("访问此页面"+LoginNum+"次了"); } } 6.3.3关闭WEB服务器,计数器被清空怎么办? 6.3.3.1简历一个record.txt文件,当tomcat关闭或者web应用重新启用的时候把访问量记录到文件中。 6.3.3.2这里要用到下面两个方法。关闭也有讲究,必须要用tomcat的shutdown,直接用Eclipse的红色按钮秒杀是不会调用销毁函数的。 那如果实际中确实是断电了/红色按钮秒杀了怎么办?用线程睡眠一定时间,定期保存就行了。 public void destroy(){ super.destroy(); System.out.println("Init destroy()被调用...."); } @Override public void init() throws ServletException{ System.out.println("init方法被调用了"); } 6.3.3.3从record.txt文件中读取访问量 A.代码 package init; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.Properties; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class Init extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); } @Override public void destroy(){ System.out.println("Init destroy()被调用...."); String filePath=this.getServletContext().getRealPath("record.txt"); FileWriter fileWriter=null; BufferedWriter bufferedWriter=null; //把servletContext的值写到文件中 try { fileWriter=new FileWriter(filePath); //为什么读取方便转成bufferedReader bufferedWriter=new BufferedWriter(fileWriter); //从servletContext读取访问量 String LoginNum=(String) this.getServletContext().getAttribute("LoginNum"); bufferedWriter.write(LoginNum); } catch (Exception e) { e.printStackTrace(); }finally{ //关闭流 try { bufferedWriter.close(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void init() throws ServletException{ System.out.println("init方法被调用了"); //首先得到该文件的全路径 String filePath=this.getServletContext().getRealPath("record.txt"); //打开此文件 try { FileReader fileReader=new FileReader(filePath); System.out.println(filePath);//这里注意了是服务器下的文件位置进一步说明了 //为什么读取方便转成bufferedReader BufferedReader bufferedReader=new BufferedReader(fileReader); String LoginNum=bufferedReader.readLine(); //把LoginNum添加到servletContext里 this.getServletContext().setAttribute("LoginNum", LoginNum); //关闭流 bufferedReader.close(); fileReader.close(); } catch (Exception e) { e.printStackTrace(); } } } B.要加强基础部分文件读取输出/服务器文件的位置其实和实际磁盘的存放位置并不相同切记。 6.3.3.4总结 A.我们建立一个record.txt记录访问次数,不至于下次启用被清空了。/需要用到init方法和destroy方法来读和写。 B.如果异常关闭怎办,使用线程的知识定时写到record的文件中去。 6.3.4 servletContext的注意事项 6.3.4.1servletContext是放在服务器的,是占用内存的,我们不建议servletContext放多太度的内容。 6.4关于SqlHelper工具类几点问题说明 6.4.1我们连接数据库的变量都是静态的。 这样有个潜在的危险,如果访问量过大,可能造成一些用户等待超时。 解决:把静态变量改成非静态变量。首先创建SqlHelper类,再调用其方法。 Servlet的晋级JSP 1.JSP第一讲 1.1十三种技术介绍 1.1.1JAVAEE是个开放的平台,它主要包括13种技术 1.1.2程序员是有选择的用,并不需要全部都掌握 1.1.3必须掌握的有JAVA/servlet/JSP/ 1.2卖油翁的故事 1.2.1JAVAMail发送电子邮件的,要学习下。 1.2.2我亦无他,唯手熟尔!熟能生巧! 1.3用户管理系统JSP版 1.3.1将servlet版本的管理系统改为JSP版本的 1.3.1.1只使用jsp完成(套路—model模式开发) 1.3.2JSP版本的管理系统改版-过渡到MV模式-更进一步过渡到MVC模式 1.4JSP概述/基本语法 1.4.1为什么会出现JSP技术 1.4.1.1程序在开发过程中发现servlet界面非常不好。 1.4.1.2JSP技术弥补了界面不好的这个缺点,JSP=html+java代码+jsp标签+js+css,是技术的综合! 1.4.1.3JSP功能强大因为可以与javaBean结合,JSP做前台(界面),javaBean做后台(逻辑层)。JSP+javaBean+servlet=mvc/ 这种模式是公司开发通用的模式。 1.4.2JSP的基本语法 1.4.2.1指令元素page指令/include指令/taglib指令 1.4.2.2脚本元素scriplet/表达式/declaration声明 1.4.2.3动作元素掌握八个就行了 1.4.2.4九大内置对象 1.5JSP运行原理 1.5.1浏览器访问JSP的过程 1.5.1.1如果是第一次访问jsp文件被服务器翻译成对应的java文件(servlet),然后再编译成class再加载到内存中。如果是以后访问 JSP文件,那就直接调用内存中的jsp实例,所以第一次访问jsp慢,后面访问jsp就快了。 1.5.2注意发现maven工程的一个问题 1.5.2.1maven工程的web-app项目,如果直接访问jsp文件或者对应的servlet.java文件,必须先在文件内部右击,点击run on server 才可以访问到JSP或者是servlet页面。注意!!!!!!!!!/如果是直接用插件tomcat启动是没有问题的,切记哦! 1.5.3JSP文件如果修改,不用重新启动 1.5.4观察JSP的代码 <!-- 声明我是一个jsp文件并且支持中文 --> <%@ page contentType="text/html;charset=utf-8"%> <!-- html代码 --> <html> <body> <h1>JSP</h1> <% //java片段 out.println("Hello JSP!中国你好!"); int a=3; int b=4; int temp=a+b; out.println("a+b="+temp); %> </body> </html> 1.5.5看下访问一次编译后的index.java文件 这个在服务器的位置让我找了好久C:UsersHIITworkspace.metadata.pluginsorg.eclipse.wst.server.core mp1workCatalinalocalhostwdfgdzxorgapachejsp package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=utf-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("<!-- 声明我是一个jsp文件并且支持中文 --> "); out.write(" "); out.write("<!-- html代码 --> "); out.write("<html> "); out.write("<body> "); out.write(" <h1>JSP</h1> "); out.write(" "); //java片段 out.println("Hello JSP!中国你好!"); int a=3; int b=4; int temp=a+b; out.println("a+b="+temp); out.write(" "); out.write("</body> "); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } } 1.5.6从上可以看出JSP和servelt的关系 1.5.6.1两者是对应关系 1.5.6.2jsp是以servelt为基础的 1.5.6.3运行原理总结过了/如果是第一次访问jsp文件被服务器翻译成对应的java文件(servlet),然后再编译成class再加载到内存中。如果是以后访问JSP文件,那就直接调用内存中的jsp实例,所以第一次访问jsp慢,后面访问jsp就快了。 1.6计算器JSP版 1.6.1知识点: 1.6.1.1如何接收jsp页面提交的数据并处理。 1.6.1.2jsp中如何使用java片段 1.6.1.3jsp如何使用js完成对数据合法性的效验 1.6.2具体的代码 1.6.2.1界面代码 <!-- 计算器的界面 --> <%@ page language="java" contentType="text/html; charset=UTF-8"%> <html> <body> <h1>计算器界面</h1> <br/> <form action="Result.jsp"> 请输入第一个数<input type="text" name="one" /> <br/> <select name="flag"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <br/> 请输入第二个数<input type="text" name="two" /><br/> <input type="submit" value="计算" /> </form> </body> </html> 1.6.2.2结果代码 <!-- 输出结果页面 --> <%@ page language="java" contentType="text/html; charset=UTF-8"%> <html> <body> <% //接受第一个数 int one=Integer.parseInt(request.getParameter("one")); //接受第二个数 int two=Integer.parseInt(request.getParameter("two")); //接受运算符号 String flag=request.getParameter("flag"); //计算结果 int result=0; if(flag.equals("+")){ result=one+two; }else if(flag.equals("-")){ result=one-two; }else if(flag.equals("*")){ result=one*two; }else if(flag.equals("/")){ result=one/two; } //输出结果 out.println("计算结果是"+result); %> </body> </html> 1.6.3JSP报错和处理 1.6.3.1如果在计算界面,第一个数没输入。 root cause java.lang.NumberFormatException: For input string: "" java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) java.lang.Integer.parseInt(Integer.java:592) java.lang.Integer.parseInt(Integer.java:615) org.apache.jsp.Calculate.Result_jsp._jspService(Result_jsp.java:60) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 1.6.3.2怎么查看呢?首先找到Result_jsp.java(注意这是jsp被服务器翻译过来的,注意原理) package org.apache.jsp.Calculate; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class Result_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("<!-- 输出结果页面 --> "); out.write(" "); out.write("<html> "); out.write("<body> "); out.write(" "); //接受第一个数 int one=Integer.parseInt(request.getParameter("one"));//这是60行 //接受第二个数 int two=Integer.parseInt(request.getParameter("two")); //接受运算符号 String flag=request.getParameter("flag"); //计算结果 int result=0; if(flag.equals("+")){ result=one+two; }else if(flag.equals("-")){ result=one-two; }else if(flag.equals("*")){ result=one*two; }else if(flag.equals("/")){ result=one/two; } //输出结果 out.println("计算结果是"+result); out.write(" "); out.write("</body> "); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } } 1.6.4 JS完成对数据合法性效验 1.6.4.1JS代码 <!-- 计算器的界面 --> <%@ 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> <!-- 在jsp中加js代码效验 --> <script type="text/javascript"> function dog() { //不能为空 if($("one").value==""||$("one").value==null||$("two").value==""||$("two").value==null){ alert("不能为空"); return false; } //判断是不是一个数 if(Math.round($("one").value)!=$("one").value||Math.round($("two").value)!=$("two").value){ alert("数据不合法"); return false; } } function $(id) { return document.getElementById(id); } </script> </head> <body> <h1>计算器界面</h1> <br /> <form name="View" action="Result.jsp"> 请输入第一个数<input type="text" name="one" id="one" /> <br /> <select name="flag"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <br /> 请输入第二个数<input type="text" name="two" id="two" /><br /> <input type="submit" value="计算" οnclick="return dog()" /> </form> </body> </html> 1.6.4.2合并都放在一个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> <!-- 在jsp中加js代码效验 --> <script type="text/javascript"> function dog() { //不能为空 if($("one").value==""||$("one").value==null||$("two").value==""||$("two").value==null){ alert("不能为空"); return false; } //判断是不是一个数 if(Math.round($("one").value)!=$("one").value||Math.round($("two").value)!=$("two").value){ alert("数据不合法"); return false; } } function $(id) { return document.getElementById(id); } </script> </head> <body> <h1>计算器界面</h1> <br /> <form name="View" action="View.jsp"> 请输入第一个数<input type="text" name="one" id="one" /> <br /> <select name="flag"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <br /> 请输入第二个数<input type="text" name="two" id="two" /><br /> <input type="submit" value="计算" οnclick="return dog()" /> </form> <hr /> <% //加了个总体判断,在一个页面实现 if(request.getParameter("one")!=null&&request.getParameter("two")!=null&& request.getParameter("flag")!=null){ //接受第一个数 int one=Integer.parseInt(request.getParameter("one")); //接受第二个数 int two=Integer.parseInt(request.getParameter("two")); //接受运算符号 String flag=request.getParameter("flag"); //计算结果 int result=0; if(flag.equals("+")){ result=one+two; }else if(flag.equals("-")){ result=one-two; }else if(flag.equals("*")){ result=one*two; }else if(flag.equals("/")){ result=one/two; } //输出结果 out.println("计算结果是"+result); } %> </body> </html> 1.6.5语法讲解 1.6.5.1表达式语法 <!-- 计算器的界面 --> <%@ 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> <!-- 在jsp中加js代码效验 --> <script type="text/javascript"> function dog() { //不能为空 if($("one").value==""||$("one").value==null||$("two").value==""||$("two").value==null){ alert("不能为空"); return false; } //判断是不是一个数 if(Math.round($("one").value)!=$("one").value||Math.round($("two").value)!=$("two").value){ alert("数据不合法"); return false; } } function $(id) { return document.getElementById(id); } </script> </head> <body> <h1>计算器界面</h1> <br /> <% //定义变量 int result=0; int one=0; int two=0; if(request.getParameter("one")!=null&&request.getParameter("two")!=null&& request.getParameter("flag")!=null){ //接受第一个数 one=Integer.parseInt(request.getParameter("one")); //接受第二个数 two=Integer.parseInt(request.getParameter("two")); //接受运算符号 String flag=request.getParameter("flag"); //计算结果 if(flag.equals("+")){ result=one+two; }else if(flag.equals("-")){ result=one-two; }else if(flag.equals("*")){ result=one*two; }else if(flag.equals("/")){ result=one/two; } } %> <form name="View" action="View.jsp"> 请输入第一个数<input type="text" name="one" id="one" value="<%=one %>"/> <br /> <select name="flag"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <br /> 请输入第二个数<input type="text" name="two" id="two" value="<%=two %>"/><br /> <input type="submit" value="计算" οnclick="return dog()" /> </form> <hr /> 计算结果是:<%=result %> </body> </html> 1.6.5.2什么是ide?其实就是集成开发环境。 1.6.6开发模式 ①A模式model1(纯jsp/jsp+class)/确定表现层和业务逻辑层混在一起,乱/不利于多人协作开发/不利于后期维护/ B简单快速,利于小项目开发 ②—model2模式— ③mvc模式 2.简单的用户登录系统【纯JSP版】 2.1第一版初级版 2.1.1登录界面 <%@ 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 action="LoginController.jsp" method="post"> 用户名<input type="text" name="username" /> <br/> 密匙码<input type="password" name="password" /><br/> <input type="submit" value="登录" /> </form> <% if(request.getParameter("err")!=null){ out.println(request.getParameter("err")); } %> </body> </html> 2.1.2控制器界面 <!-- 引包 --> <%@page import="java.sql.*,java.util.*" %> <%@ 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> <% String username=request.getParameter("username"); String password=request.getParameter("password"); //到数据库验证用户 Connection connection=null; ResultSet resultSet=null; PreparedStatement preparedStatement=null; try { //1.加载驱动 Class.forName("com.mysql.jdbc.Driver");//加载驱动 //2.得到连接 connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/my?useUnicode=true&characterEncoding=UTF-8", "root", "s5012280"); //3.预处理 preparedStatement=(PreparedStatement) connection.prepareStatement ("select *from user where username=? and password=?"); //给问号赋值 preparedStatement.setObject(1,username); preparedStatement.setObject(2,password); //4.执行操作 resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) { //说明该用户合法 System.out.println("查到数据库数值了---------"); System.out.println(request.getParameter("username")); String info=java.net.URLEncoder.encode(request.getParameter("username"),"UTF-8");//urlEncode编码如果需要转向的化 System.out.println(info); request.getRequestDispatcher("/HomePage//Admin.jsp?username="+info).forward(request, response); }else{ String temp="username or passwrod wrong!!!"; request.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(request, response); } } catch (Exception e) { e.printStackTrace(); }finally{ if(resultSet!=null){ try{ resultSet.close(); }catch(Exception e){ e.printStackTrace(); }finally{ resultSet=null;//垃圾回收 } } if(preparedStatement!=null){ try{ preparedStatement.close(); }catch(Exception e){ e.printStackTrace(); }finally{ preparedStatement=null;//垃圾回收 } } if(connection!=null){ try { connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ connection=null; } } } %> </body> </html> 2.1.3登录成功界面 <%@ 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>登录成功!</h1> <% out.println(request.getParameter("username")); %> </body> </html> 2.2用户登录系统分页有很大的优化空间 select *from user where id between 7 and 9; select top 3 * from users where id not in(select top 6 id from users);//这种用法注意核实! insert into user (username,password,level,email) select username,password,level,email from user; 2.2.1数据分页展示 2.2.1.1特别重要哈 <!-- 引包 --> <%@page import="java.sql.*,java.util.*" %> <%@ 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>登录成功!</h1> <% out.println(request.getParameter("username")); %> <h1>用户信息列表</h1> <% //定义四个分页变量 int pageSize=3; int currentPage=1; int totalNumber=0; int totalPage=0; //对currentPage进行修改,使用用户传过来的页数 if(request.getParameter("currentPage")!=null){ currentPage=Integer.parseInt(request.getParameter("currentPage")); } //查询得到totalNumber Connection connection=null; ResultSet resultSet=null; PreparedStatement preparedStatement=null; try { //1.加载驱动 Class.forName("com.mysql.jdbc.Driver");//加载驱动 //2.得到连接 connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/my?useUnicode=true&characterEncoding=UTF-8", "root", "s5012280"); //3.预处理 preparedStatement=(PreparedStatement) connection.prepareStatement ("select count(*) from user"); //4.执行操作 resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) {//一定要rs.next()下 totalNumber=resultSet.getInt(1); } //计算totalPage if(totalNumber%pageSize==0){ totalPage=totalNumber/pageSize; }else{ totalPage=totalNumber/pageSize+1; } //查询出需要显示的记录 preparedStatement=(PreparedStatement) connection.prepareStatement ("select *from user limit "+pageSize*(currentPage-1)+","+pageSize+""); resultSet=preparedStatement.executeQuery(); %> <table border="1"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>级别</td> <td>邮件</td> </tr> <% while(resultSet.next()){ %> <tr> <td><%=resultSet.getObject(1) %></td> <td><%=resultSet.getObject(2) %></td> <td><%=resultSet.getObject(3) %></td> <td><%=resultSet.getObject(4) %></td> <td><%=resultSet.getObject(5) %></td> </tr> <% } %> </table> <% //首页 out.println("<a href=Admin.jsp?currentPage=1>首页</a>"); //上一页 if(currentPage!=1){ out.println("<a href=Admin.jsp?currentPage="+(currentPage-1)+">上一页</a>"); } //显示超链接 for(int i=1;i<=totalPage;i++){ out.println("<a href=Admin.jsp?currentPage="+i+">["+i+"]</a>"); } //下一页 if(currentPage!=totalPage){ out.println("<a href=Admin.jsp?currentPage="+(currentPage+1)+">下一页</a>"); } //尾页 out.println("<a href=Admin.jsp?currentPage="+totalPage+">尾页</a>"); } catch (Exception e) { e.printStackTrace(); }finally{ if(resultSet!=null){ try{ resultSet.close(); }catch(Exception e){ e.printStackTrace(); }finally{ resultSet=null;//垃圾回收 } } if(preparedStatement!=null){ try{ preparedStatement.close(); }catch(Exception e){ e.printStackTrace(); }finally{ preparedStatement=null;//垃圾回收 } } if(connection!=null){ try { connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ connection=null; } } } %> </body> </html> 2.2.2登录系统框架改进MV(JSP+CLASS) ①A.反思:原来的代码可维护性太差/代码重复/毫无层次 B.改进方案:进行分层(界面层和业务逻辑层MV模式)/常用的封装到类中去(连接)/m就是model就是业务逻辑层 ②A.User类/UserController类/连接类(数据库类) ③开始改进 A.User类 package pojo; public class User { private int id; private String username; private String password; private String level; private String email; 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } B.连接数据库类 package util; import java.sql.*; //得到数据库的连接 public class DBUtil { private static Connection connection=null; public static Connection getConnection() { try{ //1.加载驱动 Class.forName("com.mysql.jdbc.Driver");//加载驱动 //2.得到连接 connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/my?" + "useUnicode=true&characterEncoding=UTF-8", "root", "s5012280"); }catch(Exception e){ e.printStackTrace(); } return connection; } } C.控制器 package controller; import java.sql.*; import pojo.User; import util.DBUtil; //处理类,有些人成为BO,主要是封装对User表的各种操作,无非是增删改查 public class UserController { private ResultSet resultSet=null; private PreparedStatement preparedStatement=null; private Connection connection=null; //各种方法 //验证用户是否存在 public boolean checkUser(User user){ boolean flag=false; try { connection=DBUtil.getConnection(); //3.预处理 //sql语句很重要 String sql="select *from user where username='"+user.getUsername()+"' and " + "password="+user.getPassword()+""; preparedStatement=(PreparedStatement) connection.prepareStatement(sql); //4.执行操作 System.out.println(sql); resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) { //说明该用户合法 flag=true; }else{ //不合法 flag=false; } } catch (Exception e) { e.printStackTrace(); }finally{//一定要关闭... //关闭 this.goClose(); } return flag; } //关闭资源函数 public void goClose(){ if(resultSet!=null){ try{ resultSet.close(); }catch(Exception e){ e.printStackTrace(); }finally{ resultSet=null;//垃圾回收 } } if(preparedStatement!=null){ try{ preparedStatement.close(); }catch(Exception e){ e.printStackTrace(); }finally{ preparedStatement=null;//垃圾回收 } } if(connection!=null){ try { connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ connection=null;//垃圾回收 } } } } D.界面改写 <!-- 引包 --> <%@page import="java.sql.*,java.util.*,pojo.*,controller.*,view.*" %> <%@ 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> <% String username=request.getParameter("username"); String password=request.getParameter("password"); User user=new User(); user.setUsername(username); user.setPassword(password); UserController userController=new UserController(); if(userController.checkUser(user)){ request.getRequestDispatcher("/HomePage/Admin.jsp?username="+username).forward(request, response); }else{ String temp="username or passwrod wrong!!!"; request.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(request, response); } %> </body> </html> E.管理界面改下/返回一定用集合<User>面相对象的思想。不要用RS/思想讲过 <!-- 引包 --> <%@page import="java.sql.*,java.util.*,controller.*,pojo.*" %> <%@ 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>登录成功!</h1> <% out.println(request.getParameter("username")); %> <h1>用户信息列表</h1> <% int currentPage=1; if(request.getParameter("currentPage")!=null){ currentPage=Integer.parseInt(request.getParameter("currentPage")); } //调用谁的方法来完成分页显示 UserController userController=new UserController(); User user=new User(); user.setCurrentPage(currentPage); ArrayList<User> userList=userController.getUserByPage(user); %> <table border="1"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>级别</td> <td>邮件</td> </tr> <% for(int i=0;i<userList.size();i++){ User tempUser=userList.get(i); %> <tr> <td><%=tempUser.getId() %></td> <td><%=tempUser.getUsername() %></td> <td><%=tempUser.getPassword() %></td> <td><%=tempUser.getLevel() %></td> <td><%=tempUser.getEmail() %></td> </tr> <% } %> </table> <% //首页 out.println("<a href=Admin.jsp?currentPage=1>首页</a>"); //上一页 if(currentPage!=1){ out.println("<a href=Admin.jsp?currentPage="+(currentPage-1)+">上一页</a>"); } //得到totalPage int totalNumber=userController.getTotalNumber(); int totalPage=0; if(totalNumber%3==0){ totalPage=totalNumber/3; }else{ totalPage=totalNumber/3+1; } //显示超链接 for(int i=1;i<=totalPage;i++){ out.println("<a href=Admin.jsp?currentPage="+i+">["+i+"]</a>"); } //下一页 if(currentPage!=totalPage){ out.println("<a href=Admin.jsp?currentPage="+(currentPage+1)+">下一页</a>"); } //尾页 out.println("<a href=Admin.jsp?currentPage="+totalPage+">尾页</a>"); %> </body> </html> F.最终的UserController/这里注意使用面相对象的方法 package controller; import java.sql.*; import java.util.ArrayList; import pojo.User; import util.DBUtil; //处理类,有些人成为BO,主要是封装对User表的各种操作,无非是增删改查 public class UserController { private ResultSet resultSet=null; private PreparedStatement preparedStatement=null; private Connection connection=null; //各种方法 //用户分页查询 public ArrayList<User> getUserByPage(User user){ ArrayList<User> tempUserList=new ArrayList<User>(); int pageSize=3; int currentPage=user.getCurrentPage();//这里获取到了用户传递的页数 int totalNumber=0; int totalPage=0; try { //得到总条数 totalNumber=this.getTotalNumber(); //计算总页数 if(totalNumber%pageSize==0){ totalPage=totalNumber/pageSize; }else{ totalPage=totalNumber/pageSize+1; } connection=DBUtil.getConnection();//这条不能少 //查询出需要显示的记录 preparedStatement=(PreparedStatement) connection.prepareStatement ("select *from user limit "+pageSize*(currentPage-1)+","+pageSize+""); resultSet=preparedStatement.executeQuery(); //讲rs封装到List中 while(resultSet.next()){ User tempUser=new User(); tempUser.setId(resultSet.getInt(1)); tempUser.setUsername(resultSet.getString(2)); tempUser.setPassword(resultSet.getString(3)); tempUser.setLevel(resultSet.getString(4)); tempUser.setEmail(resultSet.getString(5)); //放入到集合中 tempUserList.add(tempUser); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭 this.goClose(); } return tempUserList; } //计算总条数 public int getTotalNumber(){ int totalNumber = 0; try { connection=DBUtil.getConnection(); //3.预处理 preparedStatement=(PreparedStatement) connection.prepareStatement ("select count(*) from user"); //4.执行操作 resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) {//一定要rs.next()下 totalNumber=resultSet.getInt(1); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭 this.goClose(); } return totalNumber; } //验证用户是否存在 public boolean checkUser(User user){ boolean flag=false; try { connection=DBUtil.getConnection(); //3.预处理 //sql语句很重要 String sql="select *from user where username='"+user.getUsername()+"' and " + "password="+user.getPassword()+""; preparedStatement=(PreparedStatement) connection.prepareStatement(sql); //4.执行操作 System.out.println(sql); resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) { //说明该用户合法 flag=true; }else{ //不合法 flag=false; } } catch (Exception e) { e.printStackTrace(); }finally{//一定要关闭... //关闭 this.goClose(); } return flag; } //关闭资源函数 public void goClose(){ if(resultSet!=null){ try{ resultSet.close(); }catch(Exception e){ e.printStackTrace(); }finally{ resultSet=null;//垃圾回收 } } if(preparedStatement!=null){ try{ preparedStatement.close(); }catch(Exception e){ e.printStackTrace(); }finally{ preparedStatement=null;//垃圾回收 } } if(connection!=null){ try { connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ connection=null;//垃圾回收 } } } } ④总结 A.经过这种改变后我们发现,我们有能力写大网站了。 B.封装的思想:数据库数据——封装成List<对象> 2.2.3用户登录系统再改进MVC ①MV模式的不足 A.JSP是做界面的,验证界面调用UserController有点怪怪的 B.Admin用来显示数据,但是除了显示还调用了javaclass代码,没有优雅性,也不利于分工。 C.servlet技术页面跳转是最快捷和方便的,应该也适当使用。 ②MVC模式 A.模型、视图、控制器 B.M(工具util)主要是由java.class来做,也可以是javabean、ejb等/V由jsp来做/Cservlet来做 ③MVC模式开发(自己想法版) A.剔除LoginController.jsp/写UserController <!-- 引包 --> <%@page import="java.sql.*,java.util.*,pojo.*,controller.*,view.*,myUtil.*" %> <%@ 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> <% String username=request.getParameter("username"); String password=request.getParameter("password"); User user=new User(); user.setUsername(username); user.setPassword(password); UserControllerUtil userControllerUtil=new UserControllerUtil(); if(userControllerUtil.checkUser(user)){ request.getRequestDispatcher("/HomePage/Admin.jsp?username="+username).forward(request, response); }else{ String temp="username or passwrod wrong!!!"; request.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(request, response); } %> </body> </html> 改写成 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import myUtil.UserControllerUtil; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class UserController extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //这是一个控制器,主要调用工具完成对用户身份的验证 String username=req.getParameter("username"); String password=req.getParameter("password"); //使用模型完成对用户的验证 UserControllerUtil userControllerUtil=new UserControllerUtil(); User user=new User(); user.setUsername(username);user.setPassword(password); if(userControllerUtil.checkUser(user)){ System.out.println("调用了"); //sendredirect()重定向效率不高,最常用的是转发req.getRequestDispatcher技术 req.getRequestDispatcher("/HomePage/Admin.jsp?username="+username).forward(req, resp); }else{ String temp="username or passwrod wrong!!!"; req.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(req, resp); } } } B.登录界面 <%@ 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 action="/wdfgdzx/UserController" method="post"> 用户名<input type="text" name="username" /> <br/> 密匙码<input type="password" name="password" /><br/> <input type="submit" value="登录" /> </form> <% if(request.getParameter("err")!=null){ out.println(request.getParameter("err")); } %> </body> </html> C.处理器 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import pojo.User; import myUtil.UserControllerUtil; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class UserController extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //这是一个控制器,主要调用工具完成对用户身份的验证 String username=req.getParameter("username"); String password=req.getParameter("password"); int currentPage=1; if(req.getParameter("currentPage")!=null){ String currentPageTemp=req.getParameter("currentPage"); currentPage=Integer.parseInt(currentPageTemp); } //使用模型完成对用户的验证 UserControllerUtil userControllerUtil=new UserControllerUtil(); User user=new User(); user.setUsername(username);user.setPassword(password); user.setCurrentPage(currentPage); if(userControllerUtil.checkUser(user)){ System.out.println("调用了"); //在调转到Adimn前把数据准备好 int totalNumber=userControllerUtil.getTotalNumber(); ArrayList<User> userList=userControllerUtil.getUserByPage(user); //讲数据放到request的种 req.setAttribute("totalNumber", totalNumber+""); req.setAttribute("userList", userList); //sendredirect()重定向效率不高,最常用的是转发req.getRequestDispatcher技术 req.getRequestDispatcher("/HomePage/Admin.jsp?username="+username).forward(req, resp); }else{ String temp="username or passwrod wrong!!!"; req.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(req, resp); } } } D.处理工具 package myUtil; import java.sql.*; import java.util.ArrayList; import myUtil.DBUtil; import pojo.User; //处理类,有些人成为BO,主要是封装对User表的各种操作,无非是增删改查 public class UserControllerUtil { private ResultSet resultSet=null; private PreparedStatement preparedStatement=null; private Connection connection=null; //各种方法 //用户分页查询 public ArrayList<User> getUserByPage(User user){ ArrayList<User> tempUserList=new ArrayList<User>(); int pageSize=3; int currentPage=user.getCurrentPage();//这里获取到了用户传递的页数 int totalNumber=0; int totalPage=0; try { //得到总条数 totalNumber=this.getTotalNumber(); //计算总页数 if(totalNumber%pageSize==0){ totalPage=totalNumber/pageSize; }else{ totalPage=totalNumber/pageSize+1; } connection=DBUtil.getConnection();//这条不能少 //查询出需要显示的记录 preparedStatement=(PreparedStatement) connection.prepareStatement ("select *from user limit "+pageSize*(currentPage-1)+","+pageSize+""); resultSet=preparedStatement.executeQuery(); //讲rs封装到List中 while(resultSet.next()){ User tempUser=new User(); tempUser.setId(resultSet.getInt(1)); tempUser.setUsername(resultSet.getString(2)); tempUser.setPassword(resultSet.getString(3)); tempUser.setLevel(resultSet.getString(4)); tempUser.setEmail(resultSet.getString(5)); //放入到集合中 tempUserList.add(tempUser); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭 this.goClose(); } return tempUserList; } //计算总条数 public int getTotalNumber(){ int totalNumber = 0; try { connection=DBUtil.getConnection(); //3.预处理 preparedStatement=(PreparedStatement) connection.prepareStatement ("select count(*) from user"); //4.执行操作 resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) {//一定要rs.next()下 totalNumber=resultSet.getInt(1); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭 this.goClose(); } return totalNumber; } //验证用户是否存在 public boolean checkUser(User user){ boolean flag=false; try { connection=DBUtil.getConnection(); //3.预处理 //sql语句很重要 String sql="select *from user where username='"+user.getUsername()+"' and " + "password="+user.getPassword()+""; preparedStatement=(PreparedStatement) connection.prepareStatement(sql); //4.执行操作 System.out.println(sql); resultSet=preparedStatement.executeQuery(); //5.根据结果做处理 if(resultSet.next()) { //说明该用户合法 flag=true; }else{ //不合法 flag=false; } } catch (Exception e) { e.printStackTrace(); }finally{//一定要关闭... //关闭 this.goClose(); } return flag; } //关闭资源函数 public void goClose(){ if(resultSet!=null){ try{ resultSet.close(); }catch(Exception e){ e.printStackTrace(); }finally{ resultSet=null;//垃圾回收 } } if(preparedStatement!=null){ try{ preparedStatement.close(); }catch(Exception e){ e.printStackTrace(); }finally{ preparedStatement=null;//垃圾回收 } } if(connection!=null){ try { connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ connection=null;//垃圾回收 } } } } E.连接工具类 package myUtil; import java.sql.*; //得到数据库的连接 public class DBUtil { private static Connection connection=null; public static Connection getConnection() { try{ //1.加载驱动 Class.forName("com.mysql.jdbc.Driver");//加载驱动 //2.得到连接 connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/my?" + "useUnicode=true&characterEncoding=UTF-8", "root", "s5012280"); }catch(Exception e){ e.printStackTrace(); } return connection; } } F.管理界面 <!-- 引包 --> <%@page import="java.sql.*,java.util.*,controller.*,pojo.*,myUtil.*" %> <%@ 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>登录成功!</h1> <% out.println(request.getParameter("username")); %> <h1>用户信息列表</h1> <% int currentPage=1; if(request.getParameter("currentPage")!=null){ currentPage=Integer.parseInt(request.getParameter("currentPage")); } //显示信息从request中取 ArrayList<User> userList=(ArrayList<User>)request.getAttribute("userList"); %> <table border="1"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>级别</td> <td>邮件</td> </tr> <% for(int i=0;i<userList.size();i++){ User tempUser=userList.get(i); %> <tr> <td><%=tempUser.getId() %></td> <td><%=tempUser.getUsername() %></td> <td><%=tempUser.getPassword() %></td> <td><%=tempUser.getLevel() %></td> <td><%=tempUser.getEmail() %></td> </tr> <% } %> </table> <% //首页 String username=request.getParameter("username"); String password=request.getParameter("password"); out.println("<a href=/wdfgdzx/UserController?currentPage=1&username="+username+"&password="+password+">首页</a>"); //上一页 if(currentPage!=1){ out.println("<a href=/wdfgdzx/UserController?currentPage="+(currentPage-1)+"&username="+username+"&password="+password+">上一页</a>"); } //得到totalPage String temp=(String)request.getAttribute("totalNumber"); int totalNumber=Integer.parseInt(temp); int totalPage=0; if(totalNumber%3==0){ totalPage=totalNumber/3; }else{ totalPage=totalNumber/3+1; } //显示超链接 for(int i=1;i<=totalPage;i++){ out.println("<a href=/wdfgdzx/UserController?currentPage="+i+"&username="+username+"&password="+password+">["+i+"]</a>"); } //下一页 if(currentPage!=totalPage){ out.println("<a href=/wdfgdzx/UserController?currentPage="+(currentPage+1)+"&username="+username+"&password="+password+">下一页</a>"); } //尾页 out.println("<a href=/wdfgdzx/UserController?currentPage="+totalPage+"&username="+username+"&password="+password+">尾页</a>"); out.println("<hr/>"); out.println("<a href=/wdfgdzx/HomePage/Login.jsp>返回登录页</a>"); %> </body> </html> G.XML文件配置 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>Login</servlet-name> <servlet-class>view.Login</servlet-class> </servlet> <servlet-mapping> <servlet-name>Login</servlet-name> <url-pattern>/Login</url-pattern> </servlet-mapping> <servlet> <servlet-name>UserController</servlet-name> <servlet-class>controller.UserController</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserController</servlet-name> <url-pattern>/UserController</url-pattern> </servlet-mapping> </web-app> ④总结 A.用户操作界面—界面请求到—servlet代码办事也就是控制器—(控制器使用相关工具类M:业务逻辑处理问题)—工具类再调用连接数据库的工具类。可以有多个控制器,一类事务的处理写一个控制器,不要太少,也不要太多!工具类M处理返回数据给控制器—控制器用相应的模型返回数据给界面—返回给用户。 ⑤MVC模式的缺点 A.工作量增加了。 B.不适用小项目,好像机关枪打蚊子。 C.调试程序难度加大。 2.3session技术 2.3.1 session作用下的参数渗透 ①设置session参数 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import pojo.User; import myUtil.UserControllerUtil; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class UserController extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //设置session HttpSession session=req.getSession(); session.setAttribute("tempName", "wdfgdzx"); //这是一个控制器,主要调用工具完成对用户身份的验证 String username=req.getParameter("username"); String password=req.getParameter("password"); int currentPage=1; if(req.getParameter("currentPage")!=null){ String currentPageTemp=req.getParameter("currentPage"); currentPage=Integer.parseInt(currentPageTemp); } //使用模型完成对用户的验证 UserControllerUtil userControllerUtil=new UserControllerUtil(); User user=new User(); user.setUsername(username);user.setPassword(password); user.setCurrentPage(currentPage); if(userControllerUtil.checkUser(user)){ System.out.println("调用了"); //在调转到Adimn前把数据准备好 int totalNumber=userControllerUtil.getTotalNumber(); ArrayList<User> userList=userControllerUtil.getUserByPage(user); //讲数据放到request的种,totalNumber,userList,和currentPage放进去 req.setAttribute("totalNumber", totalNumber+""); req.setAttribute("userList", userList); req.setAttribute("currentPage", currentPage+""); //sendredirect()重定向效率不高,最常用的是转发req.getRequestDispatcher技术 req.getRequestDispatcher("/HomePage/Admin.jsp?username="+username).forward(req, resp); }else{ String temp="username or passwrod wrong!!!"; req.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(req, resp); } } } ②取出session设置的参数 <!-- 引包 --> <%@page import="java.sql.*,java.util.*,controller.*,pojo.*,myUtil.*" %> <%@ 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>登录成功!</h1> <% out.println("传递参数中取参数"+request.getParameter("username")); out.println("/session中取参数"+request.getSession().getAttribute("tempName")); %> <h1>用户信息列表</h1> <% int currentPage=1; if(request.getAttribute("currentPage")!=null){ String temp=(String)(request.getAttribute("currentPage")); currentPage=Integer.parseInt(temp); } //显示信息从request中取 ArrayList<User> userList=(ArrayList<User>)request.getAttribute("userList"); %> <table border="1"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>级别</td> <td>邮件</td> </tr> <% for(int i=0;i<userList.size();i++){ User tempUser=userList.get(i); %> <tr> <td><%=tempUser.getId() %></td> <td><%=tempUser.getUsername() %></td> <td><%=tempUser.getPassword() %></td> <td><%=tempUser.getLevel() %></td> <td><%=tempUser.getEmail() %></td> </tr> <% } %> </table> <% //首页 String username=request.getParameter("username"); String password=request.getParameter("password"); out.println("<a href=/wdfgdzx/UserController?currentPage=1&username="+username+"&password="+password+">首页</a>"); //上一页 if(currentPage!=1){ out.println("<a href=/wdfgdzx/UserController?currentPage="+(currentPage-1)+"&username="+username+"&password="+password+">上一页</a>"); } //得到totalPage String temp=(String)request.getAttribute("totalNumber"); int totalNumber=Integer.parseInt(temp); int totalPage=0; if(totalNumber%3==0){ totalPage=totalNumber/3; }else{ totalPage=totalNumber/3+1; } //显示超链接 for(int i=1;i<=totalPage;i++){ out.println("<a href=/wdfgdzx/UserController?currentPage="+i+"&username="+username+"&password="+password+">["+i+"]</a>"); } //下一页 if(currentPage!=totalPage){ out.println("<a href=/wdfgdzx/UserController?currentPage="+(currentPage+1)+"&username="+username+"&password="+password+">下一页</a>"); } //尾页 out.println("<a href=/wdfgdzx/UserController?currentPage="+totalPage+"&username="+username+"&password="+password+">尾页</a>"); out.println("<hr/>"); out.println("<a href=/wdfgdzx/HomePage/Login.jsp>返回登录页</a>"); %> </body> </html> ③中文乱码问题的处理。 2.4用户管理系统增删改查的改进 2.4.1管理界面改进 ①主页面 <%@ 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>请选择操作</h1> <% String username=request.getParameter("username"); String password=request.getParameter("password"); out.println(username); out.println(password); %> <a href="/wdfgdzx/UserController?type=Admin¤tPage=1&username=<%=username %>&password=<%=password%>">管理用户</a><br/> <a href="#">添加用户</a><br/> <a href="#">查找用户</a><br/> <a href="#">注销用户</a><br/> </body> </html> ②控制器功能增加或者增加一个控制器 package controller; import java.io.IOException; import java.sql.DriverManager; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import pojo.User; import myUtil.UserControllerUtil; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class UserController extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); //设置session HttpSession session=req.getSession(); session.setAttribute("tempName", "wdfgdzx"); //这是一个控制器,主要调用工具完成对用户身份的验证 String username=req.getParameter("username"); String password=req.getParameter("password"); String type=req.getParameter("type"); int currentPage=1; if(req.getParameter("currentPage")!=null){ String currentPageTemp=req.getParameter("currentPage"); currentPage=Integer.parseInt(currentPageTemp); } //使用模型完成对用户的验证 UserControllerUtil userControllerUtil=new UserControllerUtil(); User user=new User(); user.setUsername(username);user.setPassword(password); user.setCurrentPage(currentPage); if(userControllerUtil.checkUser(user)){ System.out.println("调用了"); //在调转到Adimn前把数据准备好 int totalNumber=userControllerUtil.getTotalNumber(); ArrayList<User> userList=userControllerUtil.getUserByPage(user); //讲数据放到request的种,totalNumber,userList,和currentPage放进去 req.setAttribute("totalNumber", totalNumber+""); req.setAttribute("userList", userList); req.setAttribute("currentPage", currentPage+""); if(type!=null&&type.equals("Admin")){ //跳转管理 req.getRequestDispatcher("/HomePage/Admin.jsp").forward(req, resp); }else{ //sendredirect()重定向效率不高,最常用的是转发req.getRequestDispatcher技术 req.getRequestDispatcher("/HomePage/MainPage.jsp?username="+username+"&password="+password+"").forward(req, resp); } }else{ String temp="username or passwrod wrong!!!"; req.getRequestDispatcher("/HomePage/Login.jsp?err="+temp).forward(req, resp); } } } ③管理界面 <!-- 引包 --> <%@page import="java.sql.*,java.util.*,controller.*,pojo.*,myUtil.*" %> <%@ 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>登录成功!</h1> <% out.println("传递参数中取参数"+request.getParameter("username")); out.println("/session中取参数"+request.getSession().getAttribute("tempName")); %> <h1>用户信息列表</h1> <% int currentPage=1; if(request.getAttribute("currentPage")!=null){ String temp=(String)(request.getAttribute("currentPage")); currentPage=Integer.parseInt(temp); } //显示信息从request中取 ArrayList<User> userList=(ArrayList<User>)request.getAttribute("userList"); %> <table border="1"> <tr> <td>ID</td> <td>姓名</td> <td>密码</td> <td>级别</td> <td>邮件</td> </tr> <% for(int i=0;i<userList.size();i++){ User tempUser=userList.get(i); %> <tr> <td><%=tempUser.getId() %></td> <td><%=tempUser.getUsername() %></td> <td><%=tempUser.getPassword() %></td> <td><%=tempUser.getLevel() %></td> <td><%=tempUser.getEmail() %></td> </tr> <% } %> </table> <% //首页 String username=request.getParameter("username"); String password=request.getParameter("password"); out.println("<a href=/wdfgdzx/UserController?type=Admin¤tPage=1&username="+username+"&password="+password+">首页</a>"); //上一页 if(currentPage!=1){ out.println("<a href=/wdfgdzx/UserController?type=Admin¤tPage="+(currentPage-1)+"&username="+username+"&password="+password+">上一页</a>"); } //得到totalPage String temp=(String)request.getAttribute("totalNumber"); int totalNumber=Integer.parseInt(temp); int totalPage=0; if(totalNumber%3==0){ totalPage=totalNumber/3; }else{ totalPage=totalNumber/3+1; } //显示超链接 for(int i=1;i<=totalPage;i++){ out.println("<a href=/wdfgdzx/UserController?type=Admin¤tPage="+i+"&username="+username+"&password="+password+">["+i+"]</a>"); } //下一页 if(currentPage!=totalPage){ out.println("<a href=/wdfgdzx/UserController?type=Admin¤tPage="+(currentPage+1)+"&username="+username+"&password="+password+">下一页</a>"); } //尾页 out.println("<a href=/wdfgdzx/UserController?type=Admin¤tPage="+totalPage+"&username="+username+"&password="+password+">尾页</a>"); out.println("<hr/>"); out.println("<a href=/wdfgdzx/HomePage/Login.jsp>返回登录页</a>"); %> </body> </html> ④分析 当然改进的可以,但是对比springmvc模式简直弱爆了,其实servlet已经实现过一次了,无法是新增个控制器增加下功能。所以后面的删改查到springmvc去实现(根据网址名称就代表不同的功能了)吧。这里不再浪费时间改进用户管理系统。 2.4.2立个flag来区分增删改的操作,做不同跳转。Spring直接名字就解决此问题了。 2.4.3使用dreamweaver来帮助写界面 3.网上购物商城(我用springmvc来做) 3.1需求分析 3.1.1系统描述 ①用户可以操作模块 ②管理员可以操作模块 3.1.2角色 ①前端用户 ②系统管理员 3.1.3用例识别 ①在角色基础上,识别出与角色相关的用例,每一个功能都是一个模块。用例罗列可以避免功能遗漏。 ②系统管理员功能/用例罗列。肯定和普通用户不同。 ③流程图梳理 3.1.4模块设计 ①模块划分和分工 3.2系统框架分析 3.2.1采用MVC的框架模式 ①我个人使用springmvc来做。知识点很多,要边听变练。 ②服务器/数据库都用原有模式 3.3网站设计 ①界面简单设计 3.4购物网站界面设计 3.4.1div+css布局 3.4.2table+css布局 3.4.3混合方式布局/推荐这种方式 3.5数据库设计 3.5.1先初步设计,然后完善,循序渐进容易接受。 3.5.2先模仿一个购物网。先模仿,后创造! 3.6网站设计代码 3.6.1界面(模仿) 3.6.2数据库(建立需要的表)—猜出表!!! ①用户表 ②管理员 ③商品表 ④公告表 3.6.3建立WEB工程 ①主页面,用dreamweaver写,界面先写死,然后再写活从数据库查图片。一般是建立html页面—>再自己改到自己的jsp页面 ②开发界面时,使用的是table+css布局。 ③在table+css布局中常用的技巧是,在行的某列中嵌如一个表格,做精确的布局。 ④初步了解下css,界面字体有点大。层叠样式表,用来控制网页的字体颜色大小背景边框的等等 ⑤头head.html页面用dreamweaver写好了。界面如何引入到jsp页面 ⑥先会用再会做,flash+js技术。A.把资源拷贝到指定到位置B.在要显示你的广告的位置加入。需要JS资源插件。具体代码使用 的时候根据实际去修改即可。 <%@ 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"> <script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script> <script src="/LeisureTime/ShopMall/ShopMallSelectSonPage/js/jPicture.min.js"></script> <script> $(function() { $("#wrapper").jPicture([ { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/1.png", href : "#1", /* text : "图片一" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/2.png", href : "#2", /* text : "图片二" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/3.png", href : "#3", /* text : "图片三" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/4.png", href : "#4", /* text : "图片四" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/5.png", href : "#5", /* text : "图片五" */ } ], { effect : "slide", dotAlign : "right", //两秒 autoplay : 2000, useTransform : true, width : 260, height : 140 }); }) </script> <table width="100%" border="0"> <tr> <td><table width="100%" border="0"> <tr> <td><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/title.png" width="100%" /></td> </tr> <tr> <td ><div id="wrapper"></div></td> </tr> </table></td> </tr> <tr> <td bgcolor="#FFCCCC"> </td> </tr> <tr> <td><table width="100%" border="0"> <tr> <td colspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/advice.png" width="100%" /></td> </tr> <tr> <td>排行榜</td> <td>商品名称</td> <td>点击数</td> </tr> <tr> <td>1</td> <td><a href="head.html">三国演义</a></td> <td>120</td> </tr> <tr> <td>2</td> <td><a href="head.html">东周列国</a></td> <td>110</td> </tr> <tr> <td>3</td> <td><a href="head.html">水浒传</a></td> <td>100</td> </tr> <tr> <td>4</td> <td><a href="head.html">城南往事</a></td> <td>90</td> </tr> <tr> <td>5</td> <td><a href="head.html">儒林外史</a></td> <td>80</td> </tr> <tr> <td>6</td> <td><a href="head.html">边城</a></td> <td>70</td> </tr> <tr> <td>7</td> <td><a href="head.html">格林童话</a></td> <td>60</td> </tr> </table></td> </tr> </table> ⑦把静态的页面向动态的页面修改! 3.6.4显示货物信息 ①具体代码 <%@ 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> <link rel="stylesheet" type="text/css" href="/LeisureTime/ShopMall/ShopMallSelectSonPage/css/mycss.css"> </head> <body> <table width="80%" border="1"> <tr> <td><jsp:include flush="true" page="/LeisureTime/ShopMall/ShopMallSelectSonPage/up.jsp"></jsp:include></td> </tr> <tr> <td height="261"><table width="100%" border="1"> <tr> <td colspan="2"> </td> </tr> <tr> <td width="25%" rowspan="8"><div> <img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/6.png" width="136" height="169" /> </div></td> <td><div>儒林外史</div></td> </tr> <tr> <td>价格:¥18</td> </tr> <tr> <td> </td> </tr> <tr> <td>ISCODE:1</td> </tr> <tr> <td>类型:历史图书</td> </tr> <tr> <td>出版商:HIT</td> </tr> <tr> <td> </td> </tr> <tr> <td>这是一个讽刺科举制的书</td> </tr> <tr> <td height="32" colspan="2"><form id="form1" name="form1" method="post" action=""> <input type="submit" name="Submit" value="购买" /> <input type="submit" name="Submit2" value="返回购物大厅" /> </form></td> </tr> <tr> <td colspan="2"> </td> </tr> </table></td> </tr> <tr> <td><jsp:include flush="true" page="/LeisureTime/ShopMall/ShopMallSelectSonPage/down.jsp"></jsp:include></td> </tr> </table> </body> </html> ②中间用到了css引入和前面写的jsp文件引入! ③然后简单跳转用mvc可以简单搞定了! ④与数据库的交互,真正动态展示书籍!可以动可以了。 ⑤动态的展示图书主界面做活。使用<c:forEach items="${shopBook.showPageList}" var="changePage" varStatus="status"> <a href="#" name="${changePage}" οnclick="giveCurrentPage(this)">[${changePage}]</a> </c:forEach></td> 搞定,包括分页展示也可以用这个循环展示出来。分页逻辑交给mvc来做 ⑥做分页切换的时候A注意当前页的js放在body后,避免有的参数没有加载。B还有注意方法(this)函数的使用,这个方法也 很重要。 3.6.5分页的设计 ①分页设计的代码 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="com.day.pojo.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <input type="hidden" name="currentPage" id="currentPage" value="${shopBook.currentPage}"/> <table width="100%" border="0"> <tr> <td colspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/give.png" width="100%" height="50%" /></td> </tr> <tr> <c:forEach items="${shopBookList}" var="changeBook" end="2" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/${changeBook.photo}" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="${pageContext.request.contextPath}/BookSelectJump.action?id=${changeBook.id}">${changeBook.bookName}</a></td> </tr> <tr> <td height="37" valign="top">价格:${changeBook.price}</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:${changeBook.bookInfo}</td> </tr> </table> </td> </c:forEach> </tr> <tr> <td colspan="3" bgcolor="#FFCCCC"> </td> </tr> <tr> <c:forEach items="${shopBookList}" var="changeBook" begin="3" end="5" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/${changeBook.photo}" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="${pageContext.request.contextPath}/BookSelectJump.action?id=${changeBook.id}">${changeBook.bookName}</a></td> </tr> <tr> <td height="37" valign="top">价格:${changeBook.price}</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:${changeBook.bookInfo}</td> </tr> </table> </td> </c:forEach> </tr> <tr> <td colspan="3"><c:forEach items="${shopBook.showPageList}" var="changePage" varStatus="status"> <a href="#" name="${changePage}" οnclick="giveCurrentPage(this)">[${changePage}]</a> </c:forEach></td> </tr> </table> ②当前页的保留 <!-- 为什么放到body后,因为有的id还没有来得及加载!!!giveCurrentPage(this)这个方法很重要! --> <script type="text/javascript"> function giveCurrentPage(myThis){ /* alert($("currentPage").value); alert(myThis.name); */ $("currentPage").value=myThis.name; document.ShopMainPage.action = "${pageContext.request.contextPath}/ShopMallSelectJump.action"; document.ShopMainPage.submit(); } function gotoBookSelect(myThis){ $("id").value=myThis.name;//这里的name指向的就是id了 document.ShopMainPage.action = "${pageContext.request.contextPath}/BookSelectJump.action"; document.ShopMainPage.submit(); } function $(id) { return document.getElementById(id); } ③这个id隐藏传递<input type="hidden" name="currentPage" id="currentPage" value="${shopBook.currentPage}" /> <input type="hidden" name="id" id="id" value="${shopBook.id}" />特别值得注意,不能使用超链接的方式,一定是document.ShopMainPage.action = "${pageContext.request.contextPath}/BookSelectJump.action"; document.ShopMainPage.submit();JS表单提交方式,提交之前可以做动作! </script> ④还有个就是最后一页如果不够3个,影响界面的问题,记得解决下!此问题用<c:if test="${shopBookList.size()>3}"> <c:forEach items="${shopBook.emptyPhotoList}" var="empty" begin="${shopBookList.size()}" end="5" varStatus="status"> 解决了,没少耽误我的时间。不过问题解决了,解决jsp代码如下! <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="com.day.pojo.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <input type="hidden" name="currentPage" id="currentPage" value="${shopBook.currentPage}" /> <input type="hidden" name="id" id="id" value="${shopBook.id}" /> <table width="100%" border="0"> <tr> <td colspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/give.png" width="100%" height="50%" /></td> </tr> <tr> <c:forEach items="${shopBookList}" var="changeBook" end="2" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/${changeBook.photo}" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="#" name="${changeBook.id}" οnclick="gotoBookSelect(this)">${changeBook.bookName}</a></td> </tr> <tr> <td height="37" valign="top">价格:¥${changeBook.price}</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:${changeBook.bookInfo}</td> </tr> </table> </td> </c:forEach> <c:if test="${shopBookList.size()<3}"> <c:forEach items="${shopBook.emptyPhotoList}" var="empty" begin="${shopBookList.size()}" end="2" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/noBook.png" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="#">暂无图书</a></td> </tr> <tr> <td height="37" valign="top">价格:¥暂无数据</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:暂无图书,敬请期待!</td> </tr> </table> </td> </c:forEach> </c:if> </tr> <tr> <td colspan="3" bgcolor="#FFCCCC"> </td> </tr> <tr> <c:forEach items="${shopBookList}" var="changeBook" begin="3" end="5" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/${changeBook.photo}" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="#" name="${changeBook.id}" οnclick="gotoBookSelect(this)">${changeBook.bookName}</a></td> </tr> <tr> <td height="37" valign="top">价格:¥${changeBook.price}</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:${changeBook.bookInfo}</td> </tr> </table> </td> </c:forEach> <c:if test="${shopBookList.size()<=3}"> <c:forEach items="${shopBook.emptyPhotoList}" var="empty" begin="3" end="5" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/noBook.png" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="#">暂无图书</a></td> </tr> <tr> <td height="37" valign="top">价格:¥暂无数据</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:暂无图书,敬请期待!</td> </tr> </table> </td> </c:forEach> </c:if> <c:if test="${shopBookList.size()>3&&shopBookList.size()<6}"> <c:forEach items="${shopBook.emptyPhotoList}" var="empty" begin="${shopBookList.size()}" end="5" varStatus="status"> <td width="33%"> <table width="100%" height="170" border="0"> <tr> <td width="30%" rowspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/tempBook/noBook.png" width="100" height="112" /></td> <td width="70%" height="37"> </td> </tr> <tr> <td height="37" valign="top"><a href="#">暂无图书</a></td> </tr> <tr> <td height="37" valign="top">价格:¥暂无数据</td> </tr> <tr> <td height="45" colspan="2" valign="top">简单介绍:暂无图书,敬请期待!</td> </tr> </table> </td> </c:forEach> </c:if> </tr> <tr> <td colspan="3"><c:forEach items="${shopBook.showPageList}" var="changePage" varStatus="status"> <a href="#" name="${changePage}" οnclick="giveCurrentPage(this)">[${changePage}]</a> </c:forEach></td> </tr> </table> ⑤分页后界面展示下! 3.6.6会员登录和注册 ①自己以前做过登录和注册了,就不再重复了! 3.6.7购物车功能 ①商品添加到购物车 A查看购物车界面 B把购物车界面写活 <c:forEach items="${buyBookList}" var="bb" varStatus="mid">,在这里犯了一个错误,注意!说明前台界面代码写错 也会影响到后台报错!!!注意问题!!! C购物车可以了,但是每一本都展示了,要重复的展示一个用到hashMap HashMap buyBookHashMap; if(httpSession.getAttribute("buyBookHashMap")!=null){ buyBookHashMap=(HashMap) httpSession.getAttribute("buyBookHashMap"); if(buyBookHashMap.containsKey(tempShopBook.getId())){ ShopBook getBookFromMap=(ShopBook) buyBookHashMap.get(tempShopBook.getId()); getBookFromMap.setBuyBookNumber(getBookFromMap.getBuyBookNumber()+1); buyBookHashMap.put(tempShopBook.getId(), getBookFromMap); }else{ buyBookHashMap.put(tempShopBook.getId(), tempShopBook);//添加书籍 } }else{ buyBookHashMap=new LinkedHashMap();//有序 buyBookHashMap.put(tempShopBook.getId(), tempShopBook);//添加书籍 httpSession.setAttribute("buyBookHashMap", buyBookHashMap);//放到session } D.前台遍历Map集合的方式也要注意下!!!这个也不对也会导致Controller报错地! <c:forEach items="${buyBookHashMap}" var="bb" varStatus="mid"> <tr> <td>${bb.value.id}</td> <td>${bb.value.bookName}</td> <td>¥${bb.value.price}</td> <td width="10%">${bb.value.buyBookNumber}</td> <td width="9%"><a href="#">删除</a></td> <td width="9%"><a href="#">查看</a></td> </tr> </c:forEach> ②商品从购物车删除 非常好,自己用MVC轻松搞定了重复商品购买展示问题和根据id删除商品的问题! ③清空购物车,这个很简单! @RequestMapping("/BuyBookCarDeleteAllBook") public ModelAndView BuyBookCarDeleteAllBook(HttpSession httpSession)throws Exception{ ModelAndView mv=new ModelAndView("/LeisureTime/ShopMall/BuyBookCar.jsp"); HashMap buyBookHashMap = (HashMap) httpSession.getAttribute("buyBookHashMap"); buyBookHashMap.clear();//这个可以和下句起到同样的作用!清空书籍Map /*httpSession.setAttribute("buyBookHashMap", null);//删除全部书籍,更新session*/ return mv; } ④修改购买商品的数量,计算价格!!!这块是难点!因为一次要修改多个数量! A<!-- 这里的name数组很关键 --> <td width="10%"> <!-- 这里需要隐藏一个id数组 --> <input type="hidden" name="idBook" value="${bb.value.id}" /> <input type="text" name="allBuyBookNumber" value="${bb.value.buyBookNumber}" /> </td> public ModelAndView BuyBookCarNumberAllUpdate(String allBuyBookNumber[],String idBook[],HttpSession httpSession)throws Exception 这个两个都是数组类型的传递,请一定注意!!! B循环修改所有idBook[ ]的allBuyBookNumber[ ],有时间学习下集合的指向性,类似于指针好像!!! @RequestMapping("/BuyBookCarNumberAllUpdate") public ModelAndView BuyBookCarNumberAllUpdate(String allBuyBookNumber[],String idBook[], HttpSession httpSession)throws Exception{ ModelAndView mv=new ModelAndView("/LeisureTime/ShopMall/BuyBookCar.jsp"); HashMap buyBookHashMap = (HashMap) httpSession.getAttribute("buyBookHashMap"); for(int i=0;i<idBook.length;i++){ //Integer.parseInt(idBook[i])一定要转一下,不然取出来的是null ShopBook getBookFromMap=(ShopBook) buyBookHashMap.get(Integer.parseInt(idBook[i])); getBookFromMap.setBuyBookNumber(Integer.parseInt(allBuyBookNumber[i])); //buyBookHashMap.put(getBookFromMap.getId(), getBookFromMap);可以不用二次放入 //可以不用再设置session } return mv; } ⑤总价格计算,还是在前端页面嵌如了一段<%java代码来计算总价格的%>记得引包和相关标签! %@ page import="com.day.pojo.*,java.util.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <% HashMap buyBookHashMap=null; if(request.getSession().getAttribute("buyBookHashMap")!=null){ buyBookHashMap=(HashMap) request.getSession().getAttribute("buyBookHashMap"); } Iterator iterator=buyBookHashMap.keySet().iterator(); double totalPrice=0.0d; while(iterator.hasNext()){ int key=(Integer) iterator.next();//可以用Integer 不能用int... ShopBook myShopBook=(ShopBook) buyBookHashMap.get(key); double tempPrice=myShopBook.getPrice()*myShopBook.getBuyBookNumber(); totalPrice=totalPrice+tempPrice; } %> <td width="48%">购物车商品总价格:¥<%= totalPrice%> 3.6.8完善剩余购物网站功能 ①显示用户联系方式,订单情况 19集42分钟! ②订单表的设计/订单的生成 ③发送电子邮件javaMail到用户的信箱 ④图书分类的代码 A界面代码 <td width="11%" height="100%"> </td> <td width="11%" height="100%"><a href="#" style="text-decoration: none" name="MainPage" οnclick="ShopMallSelectJump(this)">首页</a></td> <td width="11%" height="100%"> </td> <td width="11%" height="100%"><a href="#" style="text-decoration: none" name="history" οnclick="ShopMallSelectJump(this)">历史图书</a></td> <td width="11%" height="100%"> </td> <td width="11%" height="100%"><a href="#" style="text-decoration: none" name="liveBook" οnclick="ShopMallSelectJump(this)">生活图书</a></td> <td width="11%" height="100%"> </td> <td width="11%" height="100%"><a href="#" style="text-decoration: none">关于我们</a></td> <td width="11%" height="100%"> </td> B.JS控制代码 <input type="hidden" name="type" id="type" value="${shopBook.type}"/> function ShopMallSelectJump(myThis){ if(myThis.name=="MainPage"){ my$("type").value=""; document.ShopMainPage.action = "${pageContext.request.contextPath}/ShopMallSelectJump.action"; document.ShopMainPage.submit(); }else if(myThis.name=="history"){ my$("type").value="历史图书"; document.ShopMainPage.action = "${pageContext.request.contextPath}/ShopMallSelectJump.action"; document.ShopMainPage.submit(); }else if(myThis.name=="liveBook"){ my$("type").value="生活图书"; document.ShopMainPage.action = "${pageContext.request.contextPath}/ShopMallSelectJump.action"; document.ShopMainPage.submit(); } } ⑤根据点击量取排序的前七个书籍 select *from shop_book order by number desc limit 0,7;sql语句,按照点击数降序排列,并且只查前七位! A写<c:forEach items="${leftNumberShowList}" var="changeLeftBook" varStatus="status">遍历的时候又写错了,要注意!!! B开发尽量用调试,忘记打断点,可以启动后再打,不影响效果的! C界面代码 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="com.day.pojo.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script> <script src="/LeisureTime/ShopMall/ShopMallSelectSonPage/js/jPicture.min.js"></script> <script> $(function() { $("#wrapper").jPicture([ { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/1.png", href : "#1", /* text : "图片一" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/2.png", href : "#2", /* text : "图片二" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/3.png", href : "#3", /* text : "图片三" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/4.png", href : "#4", /* text : "图片四" */ }, { src : "/LeisureTime/ShopMall/ShopMallSelectSonPage/js/5.png", href : "#5", /* text : "图片五" */ } ], { effect : "slide", dotAlign : "right", //两秒 autoplay : 3000, useTransform : true, width : 200, height : 168 }); }) </script> <table width="100%" border="0"> <tr> <td><table width="100%" border="0"> <tr> <td><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/title.png" width="100%" height="43%" /></td> </tr> <tr> <td><div id="wrapper"></div></td> </tr> </table></td> </tr> <tr> <td bgcolor="#FFCCCC"> </td> </tr> <tr> <td><table width="100%" border="0"> <tr> <td colspan="3"><img src="/LeisureTime/ShopMall/ShopMallSelectSonPage/background/advice.png" width="100%" height="50%" /></td> </tr> <tr> <td>排行榜</td> <td>商品名称</td> <td>点击数</td> </tr> <c:forEach items="${leftNumberShowList}" var="changeLeftBook" varStatus="status"> <tr> <td>${status.index+1}</td> <!-- 点击跳转的方法前面已经写了,很好 --> <td><a href="#" name="${changeLeftBook.id}" οnclick="gotoBookSelect(this)">${changeLeftBook.bookName}</a></td> <td>${changeLeftBook.number}</td> </tr> </c:forEach> </table></td> </tr> </table> D在原来住界面基础上加两句代码! List<ShopBook> leftNumberShowList=itemService.findShopBookByOrder(shopBook); mv.addObject("shopBook", shopBook);//对应传递给页面 mv.addObject("shopBookList", shopBookList); mv.addObject("leftNumberShowList", leftNumberShowList); E.还需要更新点击数量 @RequestMapping("/BookSelectJump") public ModelAndView BookSelectJump(ShopBook shopBook)throws Exception{ ModelAndView mv=new ModelAndView("/LeisureTime/ShopMall/BookSelect.jsp"); ShopBook viewShopBook=itemService.findShopBookById(shopBook); viewShopBook.setCurrentPage(shopBook.getCurrentPage());//控制当前页面的传递 //更新数据库的点击数量 viewShopBook.setNumber(viewShopBook.getNumber()+1); itemService.updateShopBookById(viewShopBook); mv.addObject("viewShopBook", viewShopBook); return mv; } ⑥解决直接点击购物车不展示内容问题。说明一个jsp页面最好不要写ASelect.action ASelectJump.action不方便管理! A后台代码 @RequestMapping("/BuyBookCar") public ModelAndView BuyBookCar(HttpSession httpSession)throws Exception{ ModelAndView mv=new ModelAndView("/LeisureTime/ShopMall/BuyBookCar.jsp"); //这里很神奇,mv里没有添加参数buyBookHashMap,页面上我的购物车竟然还可以去到商品!牛逼啊! HashMap buyBookHashMap = null; if(httpSession.getAttribute("buyBookHashMap")!=null){ buyBookHashMap=(HashMap) httpSession.getAttribute("buyBookHashMap"); }else{//不存在创建session httpSession.setAttribute("buyBookHashMap", buyBookHashMap); buyBookHashMap=(HashMap) httpSession.getAttribute("buyBookHashMap"); } mv.addObject("buyBookHashMap", buyBookHashMap); return mv; } @RequestMapping("/BuyBookCarJump") public ModelAndView BuyBookCarJump(ShopBook shopBook,HttpSession httpSession)throws Exception{ ModelAndView mv=new ModelAndView("/LeisureTime/ShopMall/BuyBookCar.jsp"); ShopBook tempShopBook=itemService.findShopBookById(shopBook); tempShopBook.setBuyBookNumber(1);//第一次买数量是1 HashMap buyBookHashMap; if(httpSession.getAttribute("buyBookHashMap")!=null){ buyBookHashMap=(HashMap) httpSession.getAttribute("buyBookHashMap"); if(buyBookHashMap.containsKey(tempShopBook.getId())){ ShopBook getBookFromMap=(ShopBook) buyBookHashMap.get(tempShopBook.getId()); getBookFromMap.setBuyBookNumber(getBookFromMap.getBuyBookNumber()+1); buyBookHashMap.put(tempShopBook.getId(), getBookFromMap);//更新后根据id添加书籍,更改数量 }else{ buyBookHashMap.put(tempShopBook.getId(), tempShopBook);//添加书籍 } }else{ buyBookHashMap=new LinkedHashMap();//有序 buyBookHashMap.put(tempShopBook.getId(), tempShopBook);//添加书籍 httpSession.setAttribute("buyBookHashMap", buyBookHashMap);//放到session } mv.addObject("buyBookHashMap", buyBookHashMap); return mv; } B前端总价格计算 <% HashMap buyBookHashMap=null; double totalPrice=0.0d; if(request.getSession().getAttribute("buyBookHashMap")!=null){ buyBookHashMap=(HashMap) request.getSession().getAttribute("buyBookHashMap"); Iterator iterator=buyBookHashMap.keySet().iterator(); while(iterator.hasNext()){ int key=(Integer) iterator.next();//可以用Integer 不能用int... ShopBook myShopBook=(ShopBook) buyBookHashMap.get(key); double tempPrice=myShopBook.getPrice()*myShopBook.getBuyBookNumber(); totalPrice=totalPrice+tempPrice; } }else{ totalPrice=0.0d; } %> <tr> <td colspan="6"><table width="100%" border="1"> <tr> <td width="48%">购物车商品总价格:¥<%= totalPrice%>,点击 ⑦隐藏参数默认值设置注意事项! <input type="hidden" name="id" id="id" value="1" />隐藏参数的默认值最好给上,有的地方用不到隐藏参数又不给默认值 就会直接报错了!就比如到购物车界面点击首页的时候! ⑧写个人信息地址修改界面提交的时候,为什么不写重复代码自己加了一个判断。 Aif(updateRegisterRecord.getName()!=null){ itemService.updateRegister_RecordEqualName(updateRegisterRecord); } B.而界面刚好name没有传递,导致判断条件失效,自己一度怀疑前台提交问题。需要些重复代码等 C.后面要注意代码书写风格,以及用调试找到问题的根源所在!不要盲目思考问题! ⑨生成订单阶段 A设计订单数据库。数据冗余问题解决。 B经过分解表的方法,我们把32个字段,编程了18个字段了。这里其实设计到了数据表的设计模式问题。 当表和表之间有多对多关系的时候,就应该使用中间表来解决数据冗余问题。 user表 myorder表 myorder_info表 book表。 order表 和book表就是多对多! 总结:通过订单信息表 myorder_info简化了订单表 myorder和商品表book多对多的关系简化成了,一对多的关系。从而达到 解决数据冗余和复杂度的关系,而且简化了表和表的关系! 3.6.9购物车订单写库 ①写订单库没有问题,但是根据订单号写订单明细库有点技术难题,看怎么解决的。 A//但是遍历写库影响效率,我们可以使用批量操作数据的方法提高效率。 B//还必须取出刚刚添加到订单库的订单id。/取出最后那一条,这个在并发量大的时候并不一定是最好的! C暂时解决方法是,用用户名和秒时间去检索到订单,这个在限制一个账号登录的情况下和并发量不是超大的时候是可以的。 ②发送电子邮件用的是javaMail技术,主要用于发送电子邮件给某个用户信箱!百度个javaMail工具去用下! ③已经百度javaMail技术应用! 3.7springmvc开发新的总结 3.7.1 JS定义获取ID方法 一定要用my$(id),不然容易与系统默认弄混。 3.7.2定义Form表单name Form表单的名字尽量与jsp页面名字action名字保持一致,便于操作我后期维护。 3.7.3 JS函数<script></script>写的位置 尽量存放在body体后面,避免函数未加载的错误。 3.7.4隐藏参数的位置存放。 放在</Form>表达的最下面,利于知悉界面隐藏参数和后期维护。 还有不管是超链接跳转还是按钮跳转,不要用href=”超链接.action”,这样很多隐藏的参数得不到提交。一定要用href=”#” name=”xxx” οnclick=”函数(this)” this是为了区分那个按钮的作用。这种方式特别好,很直观的展示页面也能准确跳转。除非主页面跳转到个子系统不需要参数的使用才使用href=”超链接.action” 3.7.5参数传递尽量通过POJO操作 无论是数据库属性参数,还是界面要求必须参数,尽量以POJO来传递,避免参数冗余。 3.7.6时间数据修改 因为时间是date,升级时候用的是String,所以需要额外的dateAnother作为插入时间媒介。 3.7.7mapper.java中定义方法 由于mapper中需要定义对数据操作的各种方法,定义方法名称的时候尽量体现增删改查,BY后面的参数尽量体现出通过那个参数去操作。参数传递统一用POJO作为媒体,做到面相对象,参数传递明晰! 3.7.8Debug模式的使用 Web开发,特别是界面向controller传参的时候,Debug模式特别容易看到参数传递情况,利于开发Bug的排查和处理,一定要用此模式。 3.7.9必要的控制 JS界面一定判断非空或者满足正则才可以提交到后台。Controller方法中一定要判断非空和非null才执行相关的操作。否侧很容易导致系统报异常。 3.7.10 JSP知识进一步学习 JSP嵌如java代码对计算页面总价起到事半功倍的效果。JSP的foreach函数即可以遍历List集合又可以遍历Map集合,对页面数据的展示起到了至关重要的作用。对JSP中高级知识应该进一步学习。以及mapper.xml操作数据库的知识。
04-19
1095
04-19
1141
06-24
29万+
06-05
86