第一个Servlet程序
package edu.xatu;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloWordServlet extends HttpServlet {
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter ();
pw.println ( "Hello World !" );
}
}
运行结果:
servlet生命周期
package edu.xatu;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloWordServlet extends HttpServlet {
@Override
public void init () throws ServletException {
System.out.println ("初始化时第一次被调用!");
}
@Override
protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter ().println ( "service 方法" );
}
@Override
public void destroy () {
System.out.println ("在关闭服务器的情况下调用destroy方法");
}
}
运行结果:
控制台在为关闭服务器和关闭服务器的情况下的运行结果(注意对比前后的时间所输出的内容):
开发登陆系统,含登录页面、成功页面、失败页面等
创建loginServlet:
package edu.xatu;
import edu.xatu.entity.User;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String user = request.getParameter ( "username" );
String pwd = request.getParameter ( "password" );
User u = new User ();
u.setUsername ( "张三" );
u.setPassword ( "153@" );
if (user.equals ( u.getUsername () ) && pwd.equals ( u.getPassword () )){
request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
}else {
request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );
}
}
}
请求的初始化登录表单:
有没有注意到上面图片中的请求路径,是…login.jsp页面,这说明,是直接请求登录页面。这样做是有个缺点,就是使得请求路径透明化,这样也是不安全的,对吧。
所以要修改,如何修改呢?
在LoginServlet类中加入,doGet方法:
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher ( "/login.jsp" ).forward ( request,response );
}
这样请求路径就可以随便更改了。
页面效果:
没密码的情况下提交:
在输入信息错误的情况下:
在用户名和密码都正确的情况下:
error.jsp :
页面出错,点击
<a href="login.jsp">重新登录</a></br>
success.jsp :
登录成功!
login.jsp :
<script type="text/javascript">
function validate() {
if (login.username.value == ""){
alert("账号不能为空!");
return;
}
if (login.password.value == ""){
alert("密码不能为空!");
return;
}
login.submit();
}
</script>
<form name="login" action="/login" method="post">
用户名:<input type="text" name="username" value="${username}"><br>
密码: <input type="password" name="password" value="${pwd}"><br>
<input type="submit" value="登录" onclick="validate()">
</form>
开发会话跟踪的Servlet,能统计并显示同一个会话中用户访问该Servlet的次数
创建SessionServlet:
package edu.xatu;
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 java.io.IOException;
import java.io.PrintWriter;
public class SessionServlet extends HttpServlet {
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession (true); //获取session 对象
Object count = session.getAttribute ( "COUNTER" ); //取出session对象内存储的值
int counter = 0;
if (count == null){
counter = 1;
//将第一次计数存入session
session.setAttribute ( "COUNTER",new Integer ( 1 ) );
}else {
counter = ((Integer)count).intValue();
counter ++; //计数器加一
//将计数器存入session中
session.setAttribute ( "COUNTER",new Integer ( counter ) );
}
request.getRequestDispatcher ( "/welcome.jsp" ).forward ( request,response );
}
}
welcome.jsp:
欢迎来到本系统!<br>
<%
response.getWriter ().println ("该Servlet的访问次数:"+session.getAttribute ( "COUNTER" ));
%>
<sub></sub><%--sub设置下标--%>
运行结果:
它会随着刷新次数的增加而增加。
但是这样设计,显然不好。因为访问次数不可能放在页面左上方,因此,引入sub标签,试着将这个值放在下标位置,应该如何设计呢?
welcome.jsp中代码变动后:
<body>
<%
Object o = session.getAttribute ( "COUNTER" );
%>
欢迎来到本系统!
<sub>Servlet的访问次数:<%= o %></sub><%--sub设置下标--%>
</body>
运行结果:
感觉是不是很好呢?
然后是web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>edu.xatu.filter.EncodingFilter</filter-class>
</filter>
<servlet>
<servlet-name>HelloWordServlet</servlet-name>
<servlet-class>edu.xatu.HelloWordServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>edu.xatu.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>SessionServlet</servlet-name>
<servlet-class>edu.xatu.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWordServlet</servlet-name>
<url-pattern>/abc</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>SessionServlet</servlet-name>
<url-pattern>/session</url-pattern>
</servlet-mapping>
</web-app>
User:
package edu.xatu.entity;
public class User {
private String username;
private String password;
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;
}
}
处理乱码的Filter:
package edu.xatu.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding ( "utf-8" );
resp.setCharacterEncoding ( "utf-8" );
chain.doFilter ( req, resp );
}
}
运用jdbc与Servlet简单处理登录验证的问题
连接名为me的数据库,查询t_user表,验证输入的用户名和密码是否正确,要求使用PrepareStatement进行操作。
顺着这个呢,我们来做一下:
完成这些事,大概有以下几步:
1,创建数据库me,表t_user,加几个实例如下如所示:
这里的细节就略了,毕竟这不是我想表达的重点。
2,接下来是改动LoginServlet即可
package edu.xatu;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
import java.util.*;
public class LoginServlet extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String user = request.getParameter ( "username" );
String pwd = request.getParameter ( "password" );
String driverClass = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/me";
String username1 = "root";
String password = "";
//数据库连接接口
Connection conn = null;
//执行sql语句的接口
PreparedStatement prst = null;
ResultSet rs = null;
try {
//加载驱动类到虚拟机
Class.forName ( driverClass );
//连接数据库
conn = DriverManager.getConnection ( url,username1,password );
String sql = "select * from t_user where username="+"'"+user+"'"+"and password="+"'"+pwd+"'";
prst = conn.prepareStatement ( sql );
rs = prst.executeQuery ();
Map<String,String> map = new HashMap <> ( );
while (rs.next ()){
map.put ( rs.getString ( "username" ),rs.getString ( "password" ) );
if (user.equals ( rs.getString ( "username" ) ) && pwd.equals ( rs.getString ( "password" ))){
request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
}
}
if (map.isEmpty ()) request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );
} catch (Exception e) {
e.printStackTrace ();
}finally {
try {
if (prst != null)
prst.close ();
if (conn != null)
conn.close ();
} catch (SQLException e) {
e.printStackTrace ();
}
}
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher ( "/login.jsp" ).forward ( request,response );
}
}
这里面有几点注意事项:
1,mysql-connector-java-5.1.32.jar包放在WEB-INF的lib下(不然会出错哦);
2,书写格式:引入变量之后的sql:
String sql = "select * from t_user where username="+"'"+user+"'"+"and password="+"'"+pwd+"'";
3.怎样保证引入jdbc后,仍然在该Servlet中处理转发成功,失败或者其他页面呢?
这是一个比较难的问题,首先考虑的是,如果输入的结果与数据库中的不匹配,那么rs.next() 返回值为 false
所以,按照这样的逻辑就是加一个条件判断就行,注意加的位置应该在while前面:
if (!rs.next ()){...}
即:
如果出现上述编辑,那么运行结果只会出现一个(debug可知),成功页面就无法出现,异常信息是:
after end of result set
查找原因是rs.next() 用完之后会释放关闭和数据库的连接,这就导致while的rs.next()始终为false,无法向下执行。
那怎么只保证rs.next()出现一次呢,首先应该想到用某容器保存rs.next(),无果,就只能保存登陆信息。
while (rs.next ()){
map.put ( rs.getString ( "username" ),rs.getString ( "password" ) );
if (user.equals ( rs.getString ( "username" ) ) && pwd.equals ( rs.getString ( "password" ))){
request.getRequestDispatcher ( "/success.jsp" ).forward ( request,response );
}
}
因为每次用户登陆失败则map就会使空的,当然没有涉及多用户同时登陆
if (map.isEmpty ()) request.getRequestDispatcher ( "/error.jsp" ).forward ( request,response );
综上所述,最基本的前后端就串在一起了,是不是有意思的事情开始了呢?