• 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 即可。

      

  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/Rain1203/p/10919557.html
Copyright © 2020-2023  润新知