Servlet

现在我们写代码,基本都是各种框架用的飞起,提起Servlet,感觉是很久远的事情了...

但无论怎样,Servlet都是基础,各种框架都是在Servlet的基础上封装的。这篇,我们来复习下Servlet。

首先,我们先了解几个硬性概念。

1、什么是Servlet?

--简单来说Servlet就是用java编写的服务器端代码。

2、Servlet的生命周期?

1)、Web服务器首先检查是否已经装载并创建了该Servlet的实例对象;

2)、装载并创建该Servlet的一个实例对象;

3)、调用Servlet的init()方法;

4)、创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个响应Http的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去;

5)、Web应用程序被停止或重新启动之前 ,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

3、Servlet接口实现类?

--GenericServlet、HttpServlet(常用)

4、关于web.xml配置?

--由于客户端是通过url地址访问web容器中的资源,所以Servlet程序若想被外界访问,必须把Servlet程序映射到一个url地址上,这个工作由web.xml中<servlet>元素和<servlet-mapping>元素完成。

如:

<servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.rain.controller.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/UserServlet</url-pattern>
</servlet-mapping>

<servlet>元素用于注册Servlet,它包含两个元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

<servlet-mapping>元素用于映射一个已注册的Servlet的对外访问路径,它包含两个元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

需要注意的是:

1)、一个<servlet>可以对应多个<servlet-mapping>,即Servlet可以有多个对外访问路径;

2)、url-pattern中的路径也可以使用*通配符,但只有两种格式:一种是*.扩展名,另一种是以 /开头,/*结尾。

优先级判断如下:

1)、哪个精确找哪个;

2)、*.后缀的格式匹配度最低。 

 

5、Servlet中的线程安全问题?

当多个客户端并发访问同一个Servlet的时候,web服务器会为每个客户端的请求创建一个线程,并在这个线程上调用Servlet的service()方法,但是Servlet在内存中只有一个对象,因此service方法内部如果访问了同一个资源的话,就有可能引发线程安全问题。

解决方案:

1)、使用SingleThreadModel接口:不能真的防止线程安全问题(已过时);

2)、使用同步代码块(效率低下)。

需要考虑线程安全的情况:

1)、访问类变量(成员变量);

2)、访问共享资源。

最终解决方案:在Servlet中尽量减少使用类变量(成员变量),如果一定要使用类变量则用锁来防止线程安全问题。但是要注意,锁住的内容应该是造成线程安全问题的核心代码,尽量的少锁主内容,减少等待时间提高Servlet的响应速度。

OK,理论上的内容讲完了,闲话少说,贴代码,自己写的一个登录注册的例子,代码可以直接拿去用,但没有cs之类的。

 

 

环境:JDK7+Tomcat8+MySQL8

项目架构:

 

Entity:

package com.rain.entity;
/** 
 * @author 047493 
 * @version 2019年5月21日 
 * entity:实体模型层
 * User:实体类
 */
public class User {
	private int id;
	private String userName;
	private String password;
	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 getEmail(){
		return email;
	}
	public void setEmain(String email){
		this.email = email;
	}
	
	@Override
	public String toString(){
		return "User [id=" +id+ ",userName=" +userName+ ",password=" +password+ ",email=" +email+"]";
	}
}

 

 

Controller:

package com.rain.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.rain.entity.User;
import com.rain.service.UserService;
import com.rain.service.impl.UserServiceImpl;


/*@WebServlet("/UserServlet")*/
public class UserServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	UserService userService = new UserServiceImpl();
   
    public UserServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request,response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String method = request.getParameter("method");
		
		//如果传入的参数是login
		if("login".equals(method)){
			login(request,response);
		}else if("regist".equals(method)){
			regist(request,response);
		}else if("toLogin".equals(method)){
			toLogin(request,response);
		}else if("logout".equals(method)){
			logout(request,response);
		}else if("toRegist".equals(method)){
			toRegist(request,response);
		}else {
			request.setAttribute("msg", "该功能正在开发。。。");
			request.getRequestDispatcher("/message.jsp").forward(request, response);
		}
	}
	
	
	
	//注册
	private void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		User user = new User();
		
		//获取前台jsp页面参数
		String userName = request.getParameter("userName");
		String password = request.getParameter("password");
		String email = request.getParameter("email");
		
		//将接收到的参数封装到user对象中去
		user.setUserName(userName);
		user.setPassword(password);
		user.setEmain(email);
		
		//判断用户名密码是否为空
		//if(StringUtils.isNotBlank(user.getUserName()) && StringUtils.isNotBlank(user.getPassword())){
		if((userName != null && userName.length() != 0)&&(password != null && password.length() != 0)){
			int rows = userService.userRegister(user);
			if(rows > 0){
				response.setHeader("refresh", "1;url=UserServlet?method=toLogin");
			} else {
				response.setHeader("msg", "注册失败!");
				request.getRequestDispatcher("/message").forward(request, response);
			}
		} else {
			request.setAttribute("msg", "用户名密码不允许为空!");
			request.getRequestDispatcher("/message").forward(request, response);
		}
	}
	
	//登录
	public void login(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
		
		//获取前台jsp表单传递的参数
		String userName = request.getParameter("userName");
		String password = request.getParameter("password");
		
		
		//根据参数进行判断
		//1、用户名密码均不为空
		//if(StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)){
		if((userName != null && userName.length() != 0)&&(password != null && password.length() != 0)){
			//2、传递到service层登录方法
			User user = userService.userLogin(userName, password);
			//3、判断用户信息是否查询得到
			if(user != null){
				//查询到,存入session
				request.getSession().setAttribute("USER_SESSION", user);
				//登录成功,跳转至主页
				request.getRequestDispatcher("/WEB-INF/jsp/main.jsp").forward(request, response);
			}else{
				//未查询到或者用户名密码不匹配,会将失败的信息存储到msg中
				request.setAttribute("msg", "用户名或密码错误!");
				//登录失败,转向错误信息提示页,根据存入的msg取出相对应的内容
				request.getRequestDispatcher("/message.jsp").forward(request, response);
			}
		}else{
			//如果用户名或密码为空
			request.setAttribute("msg", "用户名密码不允许为空!");
			request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		}
	}
	
	//转向注册
		private void toRegist(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
			request.getRequestDispatcher("/WEB-INF/jsp/regist.jsp").forward(request, response);
		}
		
		//注销
		private void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			request.getSession().invalidate();
			request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		}

		//转向到登录页面
		private void toLogin(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
			request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		}

}

 

Service:接口+实现类

package com.rain.service;

import com.rain.entity.User;

/** 
 * @author 047493 
 * @version 2019年5月22日 
 * 业务逻辑层接口
 */
public interface UserService {
	
	//用户登录
	User userLogin(String userName,String password);
	
	//用户注册
	int userRegister(User user);
}


package com.rain.service.impl;

import com.rain.dao.impl.UserDaoImpl;
import com.rain.entity.User;
import com.rain.service.UserService;

/** 
 * @author 047493 
 * @version 2019年5月22日 
 * 业务逻辑层实现类
 */
public class UserServiceImpl implements UserService{
	private UserDaoImpl userDao = new UserDaoImpl();

	@Override
	public User userLogin(String userName, String password) {
		User user = userDao.login(userName, password);
		return user;
	}

	@Override
	public int userRegister(User user) {
		
		return userDao.regist(user);
	}

	
	
}

 DAO:接口+实现类

package com.rain.dao;

import com.rain.entity.User;

/** 
 * @author 047493 
 * @version 2019年5月21日 
 * Dao:数据持久层接口
 */
public interface UserDao {
	
	//登录
	User login(String userName,String password);
	
	//注册
	int regist(User user);
}

package com.rain.dao.impl;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.rain.dao.UserDao;
import com.rain.entity.User;
import com.rain.util.DBUtil;

/** 
 * @author 047493 
 * @version 2019年5月21日 
 * Impl:数据持久层实现
 */
public class UserDaoImpl implements UserDao{
	public static Connection conn;
	public static PreparedStatement ps;
	public static ResultSet rs;
	
	@Override
	public User login(String userName, String password) {
		String sql = "select * from t_user where userName=? and password=?";
		conn = DBUtil.getConnect();
		User user = null;
		try {
			ps = conn.prepareStatement(sql);
			ps.setString(1, userName);
			ps.setString(2, password);
			rs = ps.executeQuery();
			while(rs.next()){
				user = new User();
				user.setId(rs.getInt("id"));
				user.setUserName(rs.getString("userName"));
				user.setPassword(rs.getString("password"));
				user.setEmain(rs.getString("email"));
			}
			rs.close();
			ps.close();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return user;
	}
	@Override
	public int regist(User user) {
		String sql="insert into t_user(userName,password,email) values(?,?,?)";
		conn = DBUtil.getConnect();
		int i = 0;
		try {
			ps = conn.prepareStatement(sql);
			ps.setString(1, user.getUserName());
			ps.setString(2, user.getPassword());
			ps.setString(3, user.getEmail());
			ps.executeUpdate();
			i = 1;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return i;
	}
	
	
	
}

 Util:数据库连接类

package com.rain.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/** 
 * @author 047493 
 * @version 2019年5月21日 
 * 数据库连接工具类
 */
public class DBUtil {
	public static Connection conn;
	public static PreparedStatement ps;
	public static ResultSet rs;
	
	static{
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			System.out.println("加载数据库驱动成功!");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public static Connection getConnect(){
		Properties p = new Properties();
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		InputStream in = classLoader.getResourceAsStream("db.properties");
		String username = null;
		String password = null;
		String url = null;
		
		try {
			p.load(in);
			username = p.getProperty("username");
			password = p.getProperty("password");
			url = p.getProperty("url");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if(conn == null){
			try {
				conn = DriverManager.getConnection(url,username,password);
				System.out.println("数据库连接成功!");
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return conn;
	}
	
	public static void CloseConnection(){
		try {
			if(rs != null){
				rs.close();
			}
			if(ps != null){
				ps.close();
			}
			if(conn != null){
				conn.close();
			}
		}catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

 

db.properties:

username=root
password=123456
url=jdbc:mysql://127.0.0.1:3306/login?serverTimezone=GMT
    

 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ServletProject</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.rain.controller.UserServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/UserServlet</url-pattern>
  </servlet-mapping>
</web-app>

 index.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>
	</head>
	<body>
		<jsp:forward page="WEB-INF/jsp/regist.jsp"></jsp:forward>
	</body>
</html>

 message.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>
</head>
<body>
	${msg}
</body>
</html>

 login.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>
	</head>
	<body>
		<div class="page">
			<a id="toRegist" href="${pageContext.request.contextPath}/UserServlet?method=toRegist">没有账号,去注册?</a>
		
			<div class="login_form">
				<form id="Login" name="Login" action="${pageContext.request.contextPath}/UserServlet?method=login"  method="post">
					<table>
						<tr align="center">
							<td>请输入用户名:<input type="text" name="userName" size="20"/></td>
						</tr>
						<tr align="center">
							<td>请输入密码:<input type="password" name="password" size="20"/></td>
						</tr>
						<tr>
							<td><input type="submit" value="登录"/></td>
						</tr>
						<tr>
							<td><input type="reset" value="重置"/></td>
						</tr>
					</table>
				</form>
			
			</div>
		</div>
	</body>
</html>

 

main.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>
	</head>
	<body>
		<center>
			<h3>
				${sessionScope.USER_SESSION.userName},登录成功 
			</h3>
			
			<hr/>
			<h4>
				<a href="${pageContext.request.contextPath}/UserServlet?method=logout">退出系统</a>
			</h4>
		</center>
	</body>
</html>

 

regist.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>
	</head>
	<body>
		<form action="${pageContext.request.contextPath}/UserServlet?method=regist" method="post">
			<header>请填写表单</header>
			<fieldset>
				<a id="toLogin" href="${pageContext.request.contextPath}/UserServlet?method=toLogin">已有账号,直接登录</a>
				<br/>
				<br/>
				<section>
					<label>
						<input type="text" name="userName">
						<b>请输入用户名</b>
					</label>
				</section>
				<section>
					<label>
						<input type="password" name="password">
						<b>请输入密码</b>
					</label>
				</section>
				<section>
					<label>
						<input type="text" name="email">
						<b>请输入邮箱</b>
					</label>
				</section>
			</fieldset>
			<footer>
				<button type="submit">提交注册</button>
			</footer>
		</form>
	</body>
</html>

 

OK,访问路径:http://localhost:8080/项目名称/index.jsp 即可。

  

posted @ 2019-05-24 18:05  一枚路过的小码农  阅读(215)  评论(0编辑  收藏  举报