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

      

  • 相关阅读:
    Navicat在MySQL中添加外键详细过程
    java绘图原理------在窗口界面(或面板上)画出一张或多张图片问题解决方法
    记录springboot jar包冲突异常处理
    终止线程
    SpringDataJPA
    mysql安装后无法启动问题
    地理空间几种数据格式
    图幅与经纬度之间的换算
    postgresql12集成postgis与timescale
    C# 微信支付 V2
  • 原文地址:https://www.cnblogs.com/Rain1203/p/10919557.html
Copyright © 2020-2023  润新知