Tomact和servlet快速入门教程

  • tomcat的入门必备知识
    • 1.下载:
    • 2.安装: 解压压缩包即可
    • 3.卸载: 删除目录即可
    • 4.启动:
    • 5.关闭:
    • 6.部署:
      • 静态项目和动态项目
  • 将tomcat集成到IDEA中,并且创建JavaEE项目,部署项目
  • Servlet
    • web动态工程目录介绍
    • 热部署
    • 快速入门
    • URL地址定位实现原理
    • 生命周期方法
  • 注解配置
    • 步骤:
  • IDEA与tomcat的相关配置
  • Servlet的体系结构
  • Servlet的urlpattern配置
  • Http
    • Http请求数据格式
  • Request对象
    • Request对象的继承体系结构
    • Request的功能
      • 获取请求行数据
      • 获取请求头数据
      • 获取请求体数据
      • 获取请求参数的通用方式
        • 根据参数名获取参数值:
        • 根据参数名称获取参数值数组,多用于复选框:
        • 获取所有请求的参数名称
        • 获取所有参数的map集合
        • 请求中的中文乱码问题
    • 请求转发
      • 步骤
    • 共享数据(域对象)
    • 获取ServletContext对象
    • 用户登录案例
      • 案例需求
      • 案例分析
      • 环境准备
        • login.html中的form表单的action路径写法
    • BeanUtils工具类,简化数据封装
      • JavaBean: 标准的Java类
      • 概念
      • 方法
  • HTTP响应消息
    • 1. 响应行
    • 2. 响应头
    • 3. 响应空行
    • 4. 响应体: 传输的数据
  • Reponse对象
    • 1.设置响应行
    • 2.设置响应头
    • 3.设置响应体
  • 案例之完成重定向
    • 简单的重定向写法:
  • 重定向和转发的区别和各自特点
  • 路径写法
    • 路径分类
    • 动态获取虚拟目录
    • 服务器输出字符数据到浏览器
      • 中文乱码问题
    • 服务器输出字节数据到浏览器
    • 字节输出流案例----验证码
  • ServletContext对象
    • 获取
    • 功能
    • 1.获取MIME类型
    • 2.域对象,共享数据
    • 3.获取文件服务器路径
    • 文件下载案例
      • 中文文件名问题

tomcat的入门必备知识

1.下载:

tomcat官网下载地址

2.安装: 解压压缩包即可

注意:安装目录建议不要有中文和空格

3.卸载: 删除目录即可

4.启动:

4.1 bin/startup.bat ,双击运行该文件即可
4.2 访问:浏览器输入: http://localhost:8080 回车访问自己
或者 http://别人的ip:8080 访问别人
可以通过ipconfig:查看本机ip地址

4.3 启动可能出现的问题:

4.3.1 黑窗口一闪而过:

原因: 没有正确配置JAVA_HOME环境变量

4.3.2 启动报错:

原因: 端口号被占用

推荐的解决方法1: 找到占用的端口号,并且找到对应的进行,杀死该进程

在cmd窗口输入netstat -ano

打开任务管理器,找到刚才的进程ID,然后结束该进程

解决方法2: 修改自身端口号

conf/server.xml用记事本打开,将其默认端口号修改即可,可能还需要连带着修改其他的相关默认端口号才行

一般会把tomcat的默认端口号修改为80.
80端口号是http协议的默认端口号
好处:在访问时,就不需要输入端口号了

5.关闭:

强制关闭: 点击窗口的x
正常关闭: bin/shutdown.bat
或者ctrl+c

6.部署:

部署方式:
1.直接将项目放到webapps目录下即可
/hello: 项目的访问路径---->虚拟目录
简化部署:将项目打包成一个war包,再将war包部署到webapps目录下面
war包会自动解压缩.

2.配置conf/server.xml文件
在< Host >标签体中配置

<Context docBase="D:\hello" path="/hehe" />

docBase: 项目存放的路径
path: 虚拟目录

3.在conf\Catalina\localhost创建了一个任意名称的xml文件。
在文件中编写:

<Context docBase="D:\hello"/>

虚拟目录就是xml文件的名称

静态项目和动态项目

目录结构:
java动态项目的目录结构:
-项目根目录
–WEB-INF目录:
— web.xml: web项目的核心配置文件
—classes: 放置字节码文件的目录
—lib目录: 放置依赖的jar包


将tomcat集成到IDEA中,并且创建JavaEE项目,部署项目

tomcat集成到IDEA的教程


Servlet

概念:运行在服务器端的小程序
Servlet就是一个接口,定义了Java类被浏览器访问到的(tomcat)规则
将来我们自定义一个类,实现Servlet接口,复写方法

web动态工程目录介绍


热部署

Tomcat上的部署问题,有时候也是个麻烦的问题,要是不采用热部署,我们就只能每次对原来的文件做一次改动的时候就要重新部署,而每次重新部署都要关闭tomcat,部署完重启tomcat,可见这是一个多么烦人的事情。现在,我们可以采用热部署了,以后,就不用做烦人的关闭重起工作。

热部署的设置:


快速入门

  1. 创建JavaEE项目
  2. 定义一个类,实现Servlet的接口
  3. 实现接口中的抽象方法
  4. 配置servler

在wed.xml的< web-app >标签里面进行配置:

<?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"><!--配置Servlet--><servlet><!--servlet-name标签Servlet程序起一个别名(一般是类名)--><servlet-name>demo1</servlet-name><!--servlet-class是servlet的全类名--><servlet-class>web.servlet.servletDemo</servlet-class></servlet><!--给servlet程序配置访问地址--><servlet-mapping><!--告诉服务器,我当前配置的地址给哪个servlet程序使用--><servlet-name>demo1</servlet-name><!--配置访问地址/ 斜杠在服务器解析的时候表示地址为: http://ip:port/工程路径/demo1 表示地址为:  http://ip:port/工程路径/demo1--><url-pattern>/demo1</url-pattern></servlet-mapping>
</web-app>

常见错误:
url-pattern配置的路径中没有以斜杠打头
servlet-name配置的值不存在
servlet-class标签全类名配置错误

工程路径名修改:


URL地址定位实现原理


执行原理:
1.当服务器接收到客户端的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
2.查找web.xml文件,看是否有对应的< url-pattern >标签内容体
3.如果有,则在找到对应的< servlet-class >全类名
4.tomcat会将字节码文件加载进内存,并且创建其对象
5.调用其方法


生命周期方法

servlet中的生命周期:

  1. 被创建: 执行Init方法,只执行一次
  2. 提供服务: 执行service方法,执行多次
  3. 被销毁: 执行destory方法,只执行一次

Servlet的创建时机:
默认情况下,第一次被访问时,Servlet被创建
可以配置执行Sevlet的创建时机,如下:

<?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"><!--配置Servlet--><servlet><!--servlet-name标签Servlet程序起一个别名(一般是类名)--><servlet-name>demo1</servlet-name><!--servlet-class是servlet的全类名--><servlet-class>web.servlet.servletDemo</servlet-class><!--  指定Servlet的创建时机1.第一次被访问时,创建<load-on-startup>的值为负数2.在服务器启动时,创建<load-on-startup>的值为0或者正整数--><load-on-startup>5</load-on-startup></servlet><!--给servlet程序配置访问地址--><servlet-mapping><!--告诉服务器,我当前配置的地址给哪个servlet程序使用--><servlet-name>demo1</servlet-name><!--配置访问地址/ 斜杠在服务器解析的时候表示地址为: http://ip:port/工程路径/demo1 表示地址为:  http://ip:port/工程路径/hello--><url-pattern>/demo1</url-pattern></servlet-mapping>
</web-app>

Servlet的init方法只执行一次,说明Servlet在内存中只存在一个对象,说明Servlet是单例的

  1. 多个对象同时访问时,可能存在线程安全问题
  2. 解决: 净量不要再Servlet中定义成员变量.即使定义了成员变量也不要修改其值

每次访问Servlet时,service方法都会被调用一次

Servlet被销毁时执行。服务器关闭时,Servlet被销毁。
只有服务器正常关闭时,才会执行destory
销毁方法在对象被销毁前执行


注解配置

Servlet 3.0以上才支持注解配置,支持注解配置后,就不需要web.xml了。

对于web.xml来说,对应的每一个servlet工程都需要重新配置一个web.xml太过繁琐

步骤:

  1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
  2. 定义一个类来实现Servlet的接口
  3. 复写方法
  4. 在类上使用@WebServlet注解,进行配置


注解就是加在类上面的,因此不需要关心全类名了,也就不需要再通过name属性做对应关系了

@WebServlet(urlPatterns="资源路径");
简化写法---->注解中最重要的属性value,其实就是urlPatterns属性,因此可以省略value
@WebServlet("资源路径");



IDEA与tomcat的相关配置


Servlet的体系结构


Servlet的urlpattern配置

1. urlpattern:servlet的访问路径

2.一个servlet可以定义多个访问路径: @WebServlet({"/Demo2","/dhy","/ly"})


3.路径定义规则:

1. /xxx
2. /xxx/xxx :多层路径,目录结构

  1. *.xxx

    Servlet的url详解

Http


Http请求数据格式






Request对象


Request对象的继承体系结构


Request的功能

获取请求行数据


代码演示:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet("/RequestServlet")
public class RequestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取请求方式: GETString method=request.getMethod();System.out.println(method);//2.获取虚拟目录: /demo2String contextPath=request.getContextPath();System.out.println(contextPath);//3.获取servlet路径:/RequestServletString servletPath=request.getServletPath();System.out.println(servletPath);//4.获取get方式请求参数: name=dhyString queryString=request.getQueryString();System.out.println(queryString);//5.获取请求URI: /demo2/RequestServletString requestURI=request.getRequestURI();StringBuffer requestURL=request.getRequestURL();System.out.println(requestURI);System.out.println(requestURL);//6.获取协议及版本: HTTP/1.1String  protocol=request.getProtocol();System.out.println(protocol);//7.获取客户机的IP地址String remoteAddr=request.getRemoteAddr();System.out.println(remoteAddr);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}


获取请求头数据


获取所有头名称代码演示:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Enumeration;@WebServlet("/req")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求头数据//1.获取所有请求头名称Enumeration<String> headerNames=request.getHeaderNames();//2.遍历while(headerNames.hasMoreElements()){String name=headerNames.nextElement();//更据名称获取请求头的值String header=request.getHeader(name);System.out.println(name+"------"+header);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}


获取浏览器版本相关信息代码演示:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Enumeration;@WebServlet("/req")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//演示获取请求头数据: user-agentString agent=request.getHeader("user-agent");//不区分大小写//判断agent的浏览器版本:if(agent.contains("Chrome")){System.out.println("当前正在使用的是谷歌浏览器");}else if(agent.contains("Firefox")){System.out.println("当前正在使用火狐浏览器");}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

告诉服务器请求从哪里来—referer:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Enumeration;@WebServlet("/req")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//演示获取请求头数据: user-agent//告诉服务器请求当前servlet实例的请求从哪里来的,是否来自指定网址String referer=request.getHeader("referer");//不区分大小写System.out.println(referer); //  http://localhost:8080/demo2/login.html//防止盗链if(referer!=null){if(referer.contains("/demo2")){System.out.println("下面播放极限挑战");}else//盗链System.out.println("请付费支持正版");}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

获取请求体数据

代码演示:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;@WebServlet("/demo")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求消息体----请求参数//1.获取请求字符流BufferedReader br=request.getReader();//2.读取数据String line=null;while((line=br.readLine())!=null){System.out.println(line);}}
}

login.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title>
</head>
<body>
<form action="/demo2/demo" method="post">//action属性:设置表单提交的服务器地址<input type="text" placeholder="请输入用户名" name="username"><br><input type="text" placeholder="请输入密码" name="password"><br><input type="submit" value="注册"><br></form>
</body>
</html>


获取请求参数的通用方式

根据参数名获取参数值:

package request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;@WebServlet("/demo")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//获取get请求参数//根据参数名称获取参数值String username=request.getParameter("username");System.out.println("get方式:");System.out.println(username);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//获取post请求参数//根据参数名称获取参数值
/*        String username=request.getParameter("username");System.out.println("post方式:");System.out.println(username);*///因为doPost方法里面的代码逻辑和doGet方法里面代码逻辑相同,因此可以在doPost方法里面直接调用doGet方法//简化代码书写doGet(request,response);}
}

根据参数名称获取参数值数组,多用于复选框:

@WebServlet("/demo")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{String[] hobbies=request.getParameterValues("hobby");for(String hobby:hobbies)System.out.println(hobby);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doGet(request,response);}
}

获取所有请求的参数名称

     Enumeration<String> names= request.getParameterNames();while(names.hasMoreElements()){String name=names.nextElement();String value=request.getParameter(name);System.out.println(name+":"+value);//对于复选框,如果有多个参数值,那么这里只能获取第一个参数值,除非用数组形式获取}


获取所有参数的map集合

        Map<String, String[]> parameterMap = request.getParameterMap();Set<String> strings = parameterMap.keySet();for(String value:strings){//根据key获取值String[] strings1 = parameterMap.get(value);for(String s:strings1) {System.out.println("key=" + value + "  value=" + s);}}



上面的四种方法,第一种和第四种较为常用


请求中的中文乱码问题

  1. tomcat 8已经将get方式乱码解决,如果get方式还是有乱码,去配置中修改

  1. post方式中文会乱码

解决:
获取参数前,设置request的编码:

 //1.设置流的编码request.setCharacterEncoding("utf-8");

代码:

    @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//1.设置流的编码request.setCharacterEncoding("utf-8");Map<String, String[]> parameterMap = request.getParameterMap();Set<String> strings = parameterMap.keySet();for(String value:strings){//根据key获取值String[] strings1 = parameterMap.get(value);for(String s:strings1) {System.out.println("key=" + value + "  value=" + s);}}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doGet(request,response);}


请求转发

一种在服务器内部资源跳转的方式

步骤

代码:

@WebServlet("/demo")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{System.out.println("转发到dem0....");//转发到reqServlet3下面的资源
/*        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/reqServlet3");
requestDispatcher.forward(request,response);*///一般多为链式编程request.getRequestDispatcher("/reqServlet3").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doGet(request,response);}
}
@WebServlet("/reqServlet3")
public class reqServlet3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("转发到reqServlet3....");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}


共享数据(域对象)

域对象: 一个有作用范围的对象,可以在范围内共享数据
request 域: 代表一次请求的范围,一般用于请求转发的多个资源中共享数据

方法:

一般只有转发的情况下,才可以用request域共享数据

代码演示:

@WebServlet("/demo")
public class reqServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{System.out.println("转发到dem0....");//存储数据到request域中request.setAttribute("name","大忽悠");request.getRequestDispatcher("/reqServlet3").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{doGet(request,response);}
}
@WebServlet("/reqServlet3")
public class reqServlet3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Object name = request.getAttribute("name");System.out.println((String)name);System.out.println("转发到reqServlet3....");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}


获取ServletContext对象

 ServletContext servletContext = request.getServletContext();

用户登录案例

案例需求

案例分析

环境准备

  1. 创建项目,导入html页面,配置文件,导入jar包
  2. 创建数据库环境
USE test1;
CREATE TABLE USER(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(20) UNIQUE NOT NULL,PASSWORD VARCHAR(32) NOT NULL
);

3.创建一个user类

package domain;public class user {private int id;private  String username;private  String password;public user(int id, String username, String password) {this.id = id;this.username = username;this.password = password;}public user() {}public int getId() {return id;}public String getUsername() {return username;}public String getPassword() {return password;}public void setId(int id) {this.id = id;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}
}

4.创建操作数据库中user表的类—UserDao

package Dao;import Utils.JDBCUtils;
import domain.user;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;public class userDao {//声明JDBCTemplate对象共用private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());//登录方法public user login(user loginUser){try{//编写sql语句String sql="select * from user where username= ? and password= ?";//调用query方法---返回一个查到的user对象user user = template.queryForObject(sql, new BeanPropertyRowMapper<user>(user.class), loginUser.getUsername(), loginUser.getPassword());//loginUser: 只包含用户名和密码//返回的user: 包括用户全部数据return user;}catch (DataAccessException e){e.printStackTrace();//没有查询到,返回nullreturn null;}}}

一个例子教你看源码!深入浅出教你理解Template中的query和queryForObject的区别!

5.工具类

package Utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;public class JDBCUtils {//定义成员变量---连接池对象private static DataSource ds;static {try {//加载配置文件Properties pro=new Properties();pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));//初始化连接池对象ds= DruidDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}//获取连接池对象public static  DataSource getDataSource(){return ds;}//获取连接Connection对象public static Connection getConnection() throws SQLException {return ds.getConnection();}}
  1. loginServlet类完成登录的具体逻辑
在这里插入代码片

7.login.html

login.html中的form表单的action路径写法

虚拟目录+ Servlet的资源路径

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title>
</head>
<body>
<form action="/demo5/LoginServlet" method="post">用户名: <input type="text" name="username" placeholder="请输入用户名"><br>密码: <input type="password" placeholder="请输入密码" name="password"><br><input type="submit" value="登录">
</form>
</body>
</html>

8.配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test1
username=root
password=root
#初始化连接数量
initialSize=5
#最大连接数
maxActive=10
#最大等待时间
maxWait=3000

最新版的IDEA需要把配置文件放置到如下两个地方:

否则报如下错误:

9.loginServlet–负责登录的相关逻辑

import Dao.userDao;
import domain.user;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.设置编码request.setCharacterEncoding("utf-8");//2.获取请求参数String usermame= request.getParameter("username");String password = request.getParameter("password");//3.封装user对象user loginUser=new user(usermame,password);//4.调用userDao的login方法userDao dao=new userDao();user user=dao.login(loginUser);//5.判断userif(user==null)//登录失败request.getRequestDispatcher("/FailServlet").forward(request,response);else{//登录成功//存储数据request.setAttribute("user",user);//将查到的user对象存入//转发request.getRequestDispatcher("/SuccessServlet").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

10.FailServlet—处理登录失败的逻辑

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet("/FailServlet")
public class FailServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//给页面写一句话//设置页面的编码response.setContentType("text/html;charset=utf-8");System.out.println("登录失败");//输出response.getWriter().write("登录失败,用户名或者密码错误");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

11.SuccessServlet—处理登录成功的逻辑

import domain.user;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet("/SuccessServlet")
public class SuccessServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取request域中共享的user对象user user= (user)request.getAttribute("user");//给页面写一句话//设置编码response.setContentType("text/html;charset=utf-8");System.out.println("登录成功");//输出response.getWriter().write("欢迎"+user.getUsername()+"用户");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

效果演示:

数据库目前只有一位用户登录成功:

登录失败的演示:

登录成功的演示:



BeanUtils工具类,简化数据封装

用于封装JavaBean的

JavaBean: 标准的Java类

  1. 类必须被public修饰
  2. 必须提供空参的构造器
  3. 成员变量必须使用private修饰
  4. 必须提供公共的setter和getter方法
  5. 一般像这种JavaBean的类都会放在domain等的包下面

功能:封装数据

概念

  1. 成员变量
  2. 属性: setter和getter截取后的产物,例如: getUsername()—>Username(下一步变小写)–>username,这里的username一般就是成员变量的名字
    这里是通过通过传入的字符串和方法名截取后的产物进行比对,找到正确的方法,来设置属性值或者得到属性值

方法

  1. setProperty()—>给属性赋值
  2. getProperty()---->得到属性的值
  3. populate(Object obj,Map map):将map集合的键值对信息封装到对应的JavaBean对象中,把键作为属性的名称,值作为JavaBean对应属性的值

BeanUtils工具类使用前要导入jar包

setProperty()和getProperty()方法演示:

     user loginUser=new user();//设置loginUser的属性BeanUtils.setProperty(loginUser,"username","大忽悠");System.out.println(loginUser);

    user loginUser=new user("大忽悠","123456");String name= BeanUtils.getProperty(loginUser,"username");System.out.println(name);

populate方法演示:


/*//2.获取请求参数String usermame= request.getParameter("username");String password = request.getParameter("password");//3.封装user对象user loginUser=new user(usermame,password);
*///获取所有请求参数Map<String, String[]> parameterMap = request.getParameterMap();//创建user对象user loginUser=new user();//使用BeanUtils进行封装try {BeanUtils.populate(loginUser,parameterMap);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}

HTTP响应消息

服务器端发送给客户端的数据

数据格式:

1. 响应行

2. 响应头

3. 响应空行

4. 响应体: 传输的数据


Reponse对象

设置响应消息

1.设置响应行

  1. 格式: http/1.1 200 ok
  2. 设置状态码: setStatus(int sc)

2.设置响应头

setHeader(String name,String value);

3.设置响应体

使用步骤:

  1. 获取输出流

  2. 使用输出流,将数据输出到客户端浏览器

案例之完成重定向

重定向: 资源跳转的方式

代码演示:

        //访问Demo1资源,自动跳转到Demo2资源//1.设置状态码为302response.setStatus(302);//2.设置响应头locationresponse.setHeader("location","/Demo2Servlet");

简单的重定向写法:

 response.sendRedirect("/Demo2Servlet");

重定向和转发的区别和各自特点


路径写法

路径分类


不写默认代表./ ,即当前目录下

动态获取虚拟目录

        String contextPath = request.getContextPath();//虚拟目录response.sendRedirect(contextPath+"/Demo2Servlet");

服务器输出字符数据到浏览器

  1. 获取字符输出流
  2. 输出数据

代码演示:

        //获取字符输出流PrintWriter writer = response.getWriter();//输出数据writer.write("<font color=red size=5>Hello world</font>");


中文乱码问题

解决方法:

        //获取流对象之前,设置流的默认编码: ISO-8859-1 设置为GBKresponse.setCharacterEncoding("GBK");//获取字符输出流PrintWriter writer = response.getWriter();//输出数据writer.write("<font color=red size=5>大忽悠</font>");


如果在不知道浏览器编码格式的情况下,解决方法如下:

      //获取流对象之前,设置流的默认编码: ISO-8859-1 设置为GBKresponse.setCharacterEncoding("utf-8");//告诉浏览器,服务器发送的消息体数据编码,建议浏览器使用该编码编码response.setHeader("content-type","text/html;charset=utf-8");//获取字符输出流PrintWriter writer = response.getWriter();//输出数据----这里可以使用html标签,浏览器可以解析writer.write("<font color=red size=5>大忽悠</font>");

对上面一种方法的简化写法:

          response.setContentType("text/html;charset=utf-8");//获取字符输出流PrintWriter writer = response.getWriter();//输出数据writer.write("<font color=red size=5>大忽悠来了</font>");



服务器输出字节数据到浏览器

  1. 获取字节输出流
  2. 输出数据

代码演示:

        response.setContentType("text/html;charset=utf-8");//获取字节输出流ServletOutputStream outputStream = response.getOutputStream();//输出数据outputStream.write("大忽悠".getBytes(StandardCharsets.UTF_8));//如果这里不设置字符集,默认使用GBK

一般使用字节输出流来输出图片和视频,而非文本信息


字节输出流案例----验证码

验证码本质是个图片,目的是为了来防止恶意表单注册

完整代码演示:

Demo1Servlet:

package com.example.DEMO7;import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Random;@WebServlet("/Demo1Servlet")
public class Demo1Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int width=150;int height=50;//1.在内存中创建一个图片----创建一个不带透明色的对象BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//2.填充背景色Graphics g=image.getGraphics();//画笔对象g.setColor(Color.PINK);g.fillRect(0,0,width,height);//3.画边框g.setColor(Color.BLUE);g.drawRect(0,0,width-1,height-1);//4.随机生成验证码String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";Random ran=new Random();for(int i=1;i<=4;i++){//生成随机角标int index=ran.nextInt(str.length());//获取字符char ch=str.charAt(index);//写验证码g.drawString(ch+" ",width/5*i,height/2);}//7.画干扰线//随机生成坐标点for(int i=0;i<4;i++){int x1=ran.nextInt(width);int x2=ran.nextInt(width);int y1=ran.nextInt(height);int y2=ran.nextInt(height);g.setColor(Color.RED);g.drawLine(x1,y1,x2,y2);}//8.将图片输出到页面上----第二个参数是后缀名,第三个参数是一个输出流ImageIO.write(image,"jpg",response.getOutputStream());}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

register.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>战地六中国区官网</title><script>/** 分析:* 点击超链接或者图片,需要换一张验证码图片* 1.给超链接和图片绑定单击事件* 2.重新设置图片的src属性值* *///当页面加载完成,触发下面的事件window.onload=function (){//1.获取图片对象var img=document.getElementById("checkCode");//2.绑定单击事件img.onclick=function (){//浏览器会有缓存,因此需要加一个时间戳,保证每次的资源路径都不同var date=new Date().getTime();img.src="/Demo7/Demo1Servlet?"+date;}}</script>
</head>
<body>
<form  action="/Deom7/Demo1Servlet" method="get">游戏激活码:<input type="text" placeholder="请输入激活码"><br>验证码:<input type="text" placeholder="输入图片验证码">&nbsp;&nbsp;&nbsp;<img id="checkCode" src="/Demo7/Demo1Servlet"/><a id="change" href="http://localhost/Demo7/register.html">看不清换一张?</a>
</form>
</body>
</html>


ServletContext对象

概念: 代表整个web应用,可以和程序的容器来通信

获取


代码演示:

           //1.通过request对象获取ServletContext servletContext = request.getServletContext();//2.通过HttpServlet获取ServletContext servletContext1 = this.getServletContext();System.out.println(servletContext1);System.out.println(servletContext);System.out.println(servletContext1==servletContext);//true


功能

1.获取MIME类型


代码演示:

     //通过HttpServlet获取ServletContext servletContext = getServletContext();//定义文件名称String filename="a.jpg";//获取MIME类型String mimeType = servletContext.getMimeType(filename);System.out.println(mimeType);

2.域对象,共享数据

ServletContext对象的生命周期从服务器被创建时开始,到服务器被关闭时结束,并且作用范围很广,为所有用户,因此要谨慎使用

3.获取文件服务器路径

服务器中不同目录下的文件获取时填写路径不同,需要注意

            //获取ServletContext对象----HTTP方式ServletContext servletContext = getServletContext();//获取文件的服务器路径//web目录下的资源访问String realPath = servletContext.getRealPath("/b.txt");System.out.println(realPath);//web-inf目录下的资源访问String realPath1 = servletContext.getRealPath("/WEB-INF/c.txt");System.out.println(realPath1);//java目录下的资源访问String realPath2 = servletContext.getRealPath("/WEB-INF/classes/a.txt");System.out.println(realPath2);




文件下载案例

文件下载需求:

  1. 页面显示超链接
  2. 点击超链接后弹出下载提示框
  3. 完成图片文件下载

分析:


步骤:

上面说过的响应头相关知识回顾:

代码实现:

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求参数,即文件名称String filename=request.getParameter("filename");//使用字节输入流加载文件进内存//第一步: 找到文件服务器路径ServletContext servletContext = getServletContext();String realPath = servletContext.getRealPath("/img/" + filename);//第二步: 用字节流关联FileInputStream fis=new FileInputStream(realPath);//设置response的响应头//第一步: 设置响应头的类型: content-typeString mimeType = servletContext.getMimeType(filename);//获取文件的mime类型response.setHeader("content-type",mimeType);//第二步: 设置响应头打开的方式: content-dispositionresponse.setHeader("content-disposition","attachment;filename="+filename);//filename=....弹出提示框的名字//将输入流数据写到输出流中ServletOutputStream outputStream = response.getOutputStream();byte[] buff=new byte[1024*8];int len=0;while((len=fis.read(buff))!=-1){outputStream.write(buff,0,len);}//关闭输入流fis.close();}

downLoad.html:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title></title>
</head>
<body>
<a href="/demo9/img/cat.png">可爱小猫</a>
<a href="/demo9/img/lion.png">猛狮</a>
<hr>
<font color="#ff69b4" size="5">下面链接,点击下载图片</font><br>
<a href="/demo9/downLoadServlet?filename=cat.png">小猫图片下载</a>
<a href="/demo9/downLoadServlet?filename=lion.png">狮子图片下载</a>
</body>
</html>



中文文件名问题


解决:

如果jdk版本打印1.8,那么需要手动导入BASE64Encoder的jar包,方可使用其工具类

工具类代码:

package com.example.Demo9;
import Decoder.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class downLoadUtils {public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {if (agent.contains("MSIE")) {// IE浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+", " ");} else if (agent.contains("Firefox")) {// 火狐浏览器BASE64Encoder base64Encoder = new BASE64Encoder();filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";} else {// 其它浏览器filename = URLEncoder.encode(filename, "utf-8");}return filename;}
}

之前出问题的servlet主类:

    @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求参数,即文件名称String filename=request.getParameter("filename");//使用字节输入流加载文件进内存//第一步: 找到文件服务器路径ServletContext servletContext = getServletContext();String realPath = servletContext.getRealPath("/img/" + filename);//第二步: 用字节流关联FileInputStream fis=new FileInputStream(realPath);//设置response的响应头//第一步: 设置响应头的类型: content-typeString mimeType = servletContext.getMimeType(filename);//获取文件的mime类型response.setHeader("content-type",mimeType);//第二步: 设置响应头打开的方式: content-disposition/////解决中文文件名问题//1.获取user-agent请求头String agent=request.getHeader("user-agent");//2.使用工具类方法编码文件名即可filename = downLoadUtils.getFileName(agent, filename);///response.setHeader("content-disposition","attachment;filename="+filename);//filename=....弹出提示框的名字//将输入流数据写到输出流中ServletOutputStream outputStream = response.getOutputStream();byte[] buff=new byte[1024*8];int len=0;while((len=fis.read(buff))!=-1){outputStream.write(buff,0,len);}//关闭输入流fis.close();}

tomcat和servlet快速入门教程!!!相关推荐

  1. Servlet快速入门及运行流程

    一.Servlet快速入门 1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名 ...

  2. Day14-HTTP协议 web开发概述 servlet快速入门

    HTTP:HyperText Transfer Protocol 超文本传输协议 用于定义web浏览器和web服务器之间交换数据的过程 特点: 基于请求/响应模型的协议.请求和相应必须成对出现,现有请 ...

  3. BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序

    BIML 101 - BIML 快速入门教程 做大数据的项目,最花时间的就是数据清洗. 没有一个相对可靠的数据,数据分析就是无木之舟,无水之源. 如果你已经进了ETL这个坑,而且预算有限,并且有大量的 ...

  4. ​HealthKit开发快速入门教程大学霸内部教程

    ​HealthKit开发快速入门教程大学霸内部教程 ​ ​ 国内第一本HealthKit专向教程.本教程详细讲解iOS中,如何使用HealthKit框架开发健康应用.最后,本教程结合HealthKit ...

  5. Apple Watch开发快速入门教程

     Apple Watch开发快速入门教程  试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...

  6. 指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程

    指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程 ​1.4.2  指示灯组 指示灯组的放大图如图1.5所示. 图1.5  指示灯组 各个指示灯对应的功能如下: q  RX:对应于0号端口 ...

  7. 游戏控制杆OUYA游戏开发快速入门教程

    游戏控制杆OUYA游戏开发快速入门教程 1.2.2  游戏控制杆 游戏控制杆各个角度的视图,如图1-4所示,它的硬件规格是本文选自OUYA游戏开发快速入门教程大学霸: 图1-4  游戏控制杆各个角度的 ...

  8. Arduino Yun的主要部件介绍选自Arduino Yun快速入门教程

    Arduino Yun的主要部件介绍 1.4.1  主要部件 Yun的主要部件如图1.4所示. 图1.4  Arduino Yun的主要部件 在Yun小小的板子上集成了两颗处理器.一个是ATmega3 ...

  9. 认识AndEngine选自Android 2D游戏引擎AndEngine快速入门教程

    认识AndEngine什么是AndEngine 随着Android手机.平板的盛行,Android下的游戏也不断的变得火热.而对于游戏开发有兴趣的同学们,应该也想要学习开发游戏.虽说游戏开发的引擎较多 ...

最新文章

  1. 没项目经验,如何砍下字节算法岗40万offer
  2. Openssl自签名证书
  3. centos5.8 安装配置vsftp虚拟用户
  4. Cissp-【第4章 通信与网络安全】-2021-3-14(543页-560页)
  5. Boost:使用静态c ++内核语言扩展以进行编译和 执行模板化的c ++内核
  6. ReentrantLock源码
  7. Python3常用数据结构
  8. mysql更新代码_mysql update语句的用法
  9. Mac中找不到.bash_profile则自己创建.bash_profile文件
  10. t–sql pl–sql_SQL Server –在T-SQL中使用最低的度量单位
  11. 路由器总是有信号无网络连接到服务器,路由器信号满格但是没有网络怎么办
  12. 制作一个含生僻字的矢量字体文件(*.shx)
  13. android静态动画,Android Lottie动画实战踩坑
  14. 微信小程序使用建行支付
  15. 一个传奇玩家的传奇故事
  16. HBase-14.1-JMX监控实战-hadoop
  17. (难度:35%)untrusted游戏通关攻略
  18. 新手怎么开通抖音小店?详细操作步骤分享,建议收藏
  19. Android车机初体验
  20. (附源码)springboot音乐播放器小程序 毕业设计 170900

热门文章

  1. 用键盘打出常用符号的方法
  2. php rewriterule 规则,如何将一条RewriteCond 对应多个RewriteRule规则
  3. 超级实习生名企内推实习付费吗?与付费实习有何区别?
  4. 使用python制作的简易自习室座位预约系统
  5. div及iframe滚动条固定为最底端
  6. Java实现英文段落分句,python:对英文段落进行分句(对一段英语进行整句切分,切分句子)...
  7. 最新的三星android版本是多少,国行三星S7/S7 Edge更新最新安卓8.0系统
  8. 网络入侵敲响警钟,数据安全不容忽视!
  9. JavaScript:EventUtil.js
  10. html域名防盗链,跨域访问和防盗链基本原理(一)