Servlet应用
Servlet应用
1、首先要配置好环境
1.打开idea,选择Create New Project
2.选择Java->Web Application
3.填写项目名,选择项目路径
4.点击右上角的Add Configuration,找到Tomcate Server下的Local,再点击Create configuration
5.填写服务的名称
6.选择Deployment选项,点击右边加号,选择Artifact…
7.点击Apply,然后Ok
8.至此Tomact服务就配置好了,接下去就是配置项目文件
9.File->Project Structure
10.Modules->LoginByServletDemo(项目名)->Sources->选中WEB-INF,右击创建两个新文件,名字为:classess , lib
11.切换到Path,选择Use module compile output path,并且Output path和Test out path的路径修改为前面刚创建的classes的文件路径
12.切换到Dependencies,点击右侧加号,选择Jars or directiories…
13.选择之前创建的lib文件夹
14.选择Jar Directory
15.点击右侧加号,选择Library
16.选择Tomcat 9.0.34(也可以是其他版本号)
17.点击Apply,然后OK
18.可以先看一下index.jsp文件内容,该文件是服务启动后,默认打开的文件(也可以修改成不打开,在配置服务的时候,可以把第5点所示界面的After launch 取消勾选),然后选择刚创建的服务ServletTomcat,点击绿色三角形启动。
19.可以看到左下角已经变成了Running
20.项目启动以后,如果选择自动打开就会出现该界面(jsp界面设定的内容),若取消了自动打开,则需要手动在浏览器的网址栏中输入如图所示的地址,注意项目名不同,地址也不一样,根据自己创建的情况输入
至此,一个完整的Tomcat项目就配置好了
2、加入上一次模拟的网页项目内容+后台管理平台的网页模板
2.1 网页的内容参考 https://www.cnblogs.com/luomei/p/12873899.html ,后台管理平台的网页模板可自行下载
2.2 现在项目文件大体分为两块,src目录下存放java代码文件,web目录下存放web项目文件,但需要注意,不能把项目文件存放到WEB-INF下,WEB-INF文件下,其中classes存放预编译文件(我们不需要管),lib文件下存放项目需要的一些架包(在第一大块中有一步就是将这个包设置为项目的架包路径,所以存到到这里就可以),web.xml文件是个配置文件,功能就类似于安卓项目中的.AndroidManfest.xml文件。
2.然后把你需要的web项目文件复制到web目录下就可以,可以在文件资源管理器下复制到相应路径,也可以复制文件后,直接点击项目中的web目录,快捷键粘贴即可,下图所示,是我放入的一些项目文件,其中yinglang文件下的是后台管理的模板,login.html是上一次做好的登陆界面
3、创数据库,建立数据表,并预先填入基础信息
3.1 我选取的是Mysql数据库,有需要的可以自行安装,或者推荐一个软件xmapp,可以避免很多配置mysql时候的各种错误
3.2 可视化工具可以选择MySQL Workbench,界面比较简洁,能快速的完成直接对表进行增删改查的操作。
3.3 下图所示是已经创建好的表内容:
4、编写一个servlet进行用户名和密码校验,获取登录页面的用户名密码,并显示出来(代码和截图的包路径可能有些出入,因为代码是项目整体完成后添加的,根据实际情况修改即可)
4.1 在正式进行代码的编写前,我发现我的idea无法使用new快速创建servlet的相关文件,在查询了相关资料以后,发现,需要在.iml文件中加上红框中的内容
4.2 创建一个Servlet文件
4.3 在web.xml文件中配置Servlet
4.3 因为要连接数据库,所以还要下载mysql对应的架包,并存放到WEB-INF下的lib文件中
4.4 编写服务器端代码
4.4.1 数据库连接
1 package JDBCHelper; 2 import com.mysql.jdbc.StatementImpl; 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 /* 7 * 数据库连接 8 */ 9 public class MySqlDBUtil { 10 public static Connection getConnection() { 11 Connection connection = null; 12 try { 13 Class.forName("com.mysql.jdbc.Driver"); 14 connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/servletdata?useSSL=true&characterEncoding=utf-8&user=root&password="); 15 System.out.println("数据库连接成功!"); 16 System.out.println("-------------------------------"); 17 return connection; 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 System.out.println("创建连接失败!"); 22 System.out.println("-------------------------------"); 23 return null; 24 } 25 public static void ShutDown(StatementImpl statement, Connection connection) { 26 if (statement != null) { 27 try { 28 statement.close(); 29 } catch (SQLException e) { 30 e.printStackTrace(); 31 } 32 } 33 if (connection != null) { 34 try { 35 connection.close(); 36 } catch (SQLException e) { 37 e.printStackTrace(); 38 } 39 40 } 41 } 42 }
4.4.2 数据表查询
1 package JDBCHelper; 2 3 import TableObject.Users; 4 import com.mysql.jdbc.PreparedStatement; 5 import java.sql.Connection; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 9 public class UsersTableUtil { 10 //登陆校验 11 public boolean IsUsersExist(Connection con, Users user) { 12 try { 13 //验证用户名存在性 14 PreparedStatement pstmt; 15 String sql = "select * from users where username=? and password=?"; 16 pstmt= (PreparedStatement) con.prepareStatement(sql); 17 pstmt.setString(1,user.getName()); 18 pstmt.setString(2,user.getPassword()); 19 ResultSet rs=pstmt.executeQuery(); 20 if (rs.next()) { 21 //关闭数据库 22 MySqlDBUtil.ShutDown(pstmt,null); 23 return true; 24 } 25 MySqlDBUtil.ShutDown(pstmt,null); 26 return false; 27 } catch (SQLException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 return false; 31 } 32 } 33 }
4.4.3 用户表所对应的用户类
1 package TableObject; 2 3 public class Users { 4 String name="";//用户名 5 String password="";//用户密码 6 7 public String getName() { 8 return name; 9 } 10 11 public void setName(String name) { 12 this.name = name; 13 } 14 15 public String getPassword() { 16 return password; 17 } 18 19 public void setPassword(String password) { 20 this.password = password; 21 } 22 }
4.4.4 刚创建的LoginServlet的代码
1 package Servlet; 2 3 import JDBCHelper.MySqlDBUtil; 4 import JDBCHelper.UsersTableUtil; 5 import TableObject.Users; 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import java.io.IOException; 12 import java.sql.Connection; 13 14 @WebServlet(name = "Servlet.LoginServlet") 15 public class LoginServlet extends HttpServlet { 16 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { 17 //设置成与浏览器不同的编码方式,测试过滤器 18 //response.setContentType("text/html;charset=GB2312"); 19 //request.setCharacterEncoding("GB2312"); 20 //与浏览器相同的编码方式 21 response.setContentType("text/html;charset=utf-8"); 22 request.setCharacterEncoding("utf-8"); 23 //连接数据库 24 Connection connection= MySqlDBUtil.getConnection(); 25 //Login的处理 26 Login(request,response,connection); 27 //关闭数据库 28 MySqlDBUtil.ShutDown(null,connection); 29 } 30 void Login(HttpServletRequest request, HttpServletResponse response,Connection connection) throws IOException { 31 //获取表单中的数据的值 32 Users user=new Users(); 33 user.setName(request.getParameter("username")); 34 user.setPassword(request.getParameter("password")); 35 System.out.println("登入用户名:"+user.getName()); 36 System.out.println("登入用户密码:"+user.getPassword()); 37 //验证用户名密码 38 UsersTableUtil ur = new UsersTableUtil(); 39 boolean b = ur.IsUsersExist(connection, user); 40 System.out.println("是否存在该用户:"+b); 41 System.out.println("-------------------------------"); 42 if(b){ 43 //成功登录,进入主界面 44 response.sendRedirect("yinglang/index.html"); 45 }else 46 { 47 response.getWriter().println("登陆失败"); 48 //登录失败,返回登陆界面 49 response.sendRedirect("login.html"); 50 System.out.println("Login Failed!"); 51 } 52 } 53 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 54 55 } 56 }
4.4.5 还需要修改login.html文件,红框中的注意修改即可
结果展示:
5、使用cookie,保存登录信息,30天内,用户无需登录
5.1 一个工具类来专门保存cookie
1 package Util; 2 3 import javax.servlet.http.Cookie; 4 import javax.servlet.http.HttpServletResponse; 5 6 public class CookieSave { 7 public void Save(HttpServletResponse response,String name,String value,int last_time) 8 { 9 //创建Cookie,将用户名存到叫cookieUserName的cookie中 10 //Cookie 对象携带需要保存的数据,user.getName()=value,都是字符串类型 11 //每个cookie保存一个数据,如果需要多个,创建多个cookie对象 12 Cookie cookieUserName = new Cookie(name, value); 13 //设置cookie存在时间 单位:秒 14 //cookie保存的时间,不管中途是否使用,访问cookie,到时就过期 15 //如果不设置,那么cookie在浏览器关闭的时候失效 16 cookieUserName.setMaxAge(last_time); 17 //将cookie发给浏览器(如果没有这句,cookie就不会发送给客户端) 18 response.addCookie(cookieUserName); 19 } 20 }
5.2 将loginservlet中成功验证的代码修改为:
1 if(b){ 2 CookieSave cookieSave=new CookieSave(); 3 //存储用户名 4 cookieSave.Save(response,"username",user.getName(),60*60*24*30); 5 //存储密码 6 cookieSave.Save(response,"password",user.getPassword(),60*60*24*30); 7 //成功登录,进入主界面 8 response.sendRedirect("yinglang/index.html"); 9 }
5.3 完成上面两步只是完成了cookie的存储,还需要实现当页面打开后自动填充已保存的cookie,所以还需要在login.html的js代码中添加如下关于cookie操作的代码:
1 function getCookie(cname){ 2 var name = cname + "="; 3 var ca = document.cookie.split(';'); 4 for(var i=0; i<ca.length; i++) { 5 var c = ca[i].trim(); 6 if (c.indexOf(name)==0) { return c.substring(name.length,c.length); } 7 } 8 return ""; 9 } 10 function checkCookie(){ 11 var user=getCookie("username"); 12 var uname=document.getElementById("username"); 13 var pwd=getCookie("password"); 14 var upwd=document.getElementById("password"); 15 16 if (user!=""&&pwd!=""){ 17 uname.value=user; 18 upwd.value=pwd; 19 } 20 } 21 window.onload=function()//用window的onload事件,窗体加载完毕的时候 22 { 23 checkCookie(); 24 }
结果展示,可以看到时间设置是正确的30天:
6、使用session,显示网站当前在线人数
6.1 建立一个HttpSessionListener类,并也在web.xml中添加配置
1 package Servlet; 2 3 import javax.servlet.annotation.WebListener; 4 import javax.servlet.http.HttpSession; 5 import javax.servlet.http.HttpSessionEvent; 6 import javax.servlet.http.HttpSessionListener; 7 import java.text.SimpleDateFormat; 8 import java.util.Date; 9 10 @WebListener() 11 public class OnlineCounterListener implements HttpSessionListener { 12 //number of online 13 public static int activeSessions = 0; 14 15 /* Session创建事件 */ 16 public void sessionCreated(HttpSessionEvent se) { 17 activeSessions++; 18 System.out.println("newSession.id=" + se.getSession().getId() + "-->The number of online is " + Integer.toString(activeSessions)); 19 HttpSession session = se.getSession(); 20 // 获取 session 创建时间 21 Date createTime = new Date(session.getCreationTime()); 22 //设置日期输出的格式 23 SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 24 System.out.println("createtime=" + df.format(createTime)); 25 System.out.println("-------------------------------"); 26 27 } 28 29 /* Session失效事件 */ 30 public void sessionDestroyed(HttpSessionEvent se) { 31 activeSessions--; 32 System.out.println("outSession.id=" + se.getSession().getId() + "-->The number of online is " + Integer.toString(activeSessions)); 33 HttpSession session = se.getSession(); 34 // 获取该网页的最后一次访问时间 35 Date lastAccessTime = new Date(session.getLastAccessedTime()); 36 //设置日期输出的格式 37 SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 38 System.out.println("The lastAccessTime " + df.format(lastAccessTime)); 39 System.out.println("-------------------------------"); 40 } 41 }
web.xml
<!-- 配置监听--> <listener> <listener-class>Servlet.OnlineCounterListener</listener-class> </listener>
6.2 再添加一个session的servlet,用来获取当前的在线人数,当然,也要在web.xml中添加配置
1 package Servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 import static Servlet.OnlineCounterListener.activeSessions; 11 12 @WebServlet(name = "GetSession") 13 public class GetSession extends HttpServlet { 14 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 15 } 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 response.getWriter().println("The number of online : "+Integer.toString(activeSessions)); 18 } 19 }
web.xml
<servlet> <servlet-name>GetSession</servlet-name> <servlet-class>Servlet.GetSession</servlet-class> </servlet> <servlet-mapping> <servlet-name>GetSession</servlet-name> <url-pattern>/GetSession</url-pattern> </servlet-mapping>
6.3 在loginservlet的代码中,成功登陆后加上一句代码就可以了,可以利用session完成一些操作,因为该功能只需要计数,利用监听部分的代码就可以完成了,在这里添加这一句是为了让监听响应到session的创建。
HttpSession session =request.getSession(true);
6.4 在长时间未响应后,需要断开session,这里采用在web.xml中添加配置的方式
<session-config> <session-timeout>3</session-timeout> </session-config>
结果展示(这里需要把自动打开浏览器的那个after launch取消勾选,不然会不知道从哪儿冒出来两个session,其次,一个浏览器一个session,可以用查看cookie的方式看到对应的session值):
7、使用过滤器解决乱码问题,登录时用户名为中文可能不能正常识别,解决该问题
7.1 建立一个Filter,同样也需要在web.xml中配置
1 package Servlet; 2 3 import javax.servlet.*; 4 import javax.servlet.annotation.WebFilter; 5 import java.io.IOException; 6 7 @WebFilter(filterName = "GBFilter") 8 public class GBFilter implements Filter { 9 public void destroy() { 10 } 11 12 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { 13 String encoding =req.getCharacterEncoding(); 14 System.out.println("Before encoding "+encoding+" filter!"); 15 encoding="utf-8";//新编码 16 req.setCharacterEncoding(encoding); 17 resp.setContentType("text/html;charset="+encoding); 18 System.out.println("after encoding "+encoding+" filter!"); 19 System.out.println("-------------------------------------"); 20 chain.doFilter(req, resp); 21 } 22 23 public void init(FilterConfig config) throws ServletException { 24 } 25 }
web.xml
<!--配置filter--> <filter> <filter-name>GBFilter</filter-name> <filter-class>Servlet.GBFilter</filter-class> </filter> <filter-mapping> <filter-name>GBFilter</filter-name> <!--拦截规则--> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
7.2 模拟服务端和客户端编码方式不同的情况,这里我们先注释掉web.xml中的filter,然后将loginservlet中编码部分修改成与login.html不同的编码方式,我的项目文件中login.html编码为utf-8
7.3 未使用过滤器,且服务端与客户端编码方式不同的模拟结果,可以看到小明这两个中文字已经变成了乱码
7.4 取消过滤器在web.xml中的注释,且注释loginservlet中设定编码的两句代码后再次查看结果,发现乱码问题已经被解决了
8.码云地址
https://gitee.com/MavisLuo/servlet
PS.添加了过滤器一段时间后,可能会出现打开的界面出现文字乱码或者css样式丢失的情况,可以先把项目中的filter的配置注释一下,然后删除项目中的out文件,并将乱码的浏览器的缓存文件清除,建议清楚24小时以内,因为1小时以内可能也没有清除干净,再重启浏览器,大概率能解决掉这个问题。造成这个问题的具体原因还不清楚。(我这里用的是谷歌浏览器)