tomcat和servlet快速入门教程!!!
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,可见这是一个多么烦人的事情。现在,我们可以采用热部署了,以后,就不用做烦人的关闭重起工作。
热部署的设置:
快速入门
- 创建JavaEE项目
- 定义一个类,实现Servlet的接口
- 实现接口中的抽象方法
- 配置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中的生命周期:
- 被创建: 执行Init方法,只执行一次
- 提供服务: 执行service方法,执行多次
- 被销毁: 执行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是单例的
- 多个对象同时访问时,可能存在线程安全问题
- 解决: 净量不要再Servlet中定义成员变量.即使定义了成员变量也不要修改其值
每次访问Servlet时,service方法都会被调用一次
Servlet被销毁时执行。服务器关闭时,Servlet被销毁。
只有服务器正常关闭时,才会执行destory
销毁方法在对象被销毁前执行
注解配置
Servlet 3.0以上才支持注解配置,支持注解配置后,就不需要web.xml了。
对于web.xml来说,对应的每一个servlet工程都需要重新配置一个web.xml太过繁琐
步骤:
- 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
- 定义一个类来实现Servlet的接口
- 复写方法
- 在类上使用@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 :多层路径,目录结构
- *.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);}}
上面的四种方法,第一种和第四种较为常用
请求中的中文乱码问题
- tomcat 8已经将get方式乱码解决,如果get方式还是有乱码,去配置中修改
- 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();
用户登录案例
案例需求
案例分析
环境准备
- 创建项目,导入html页面,配置文件,导入jar包
- 创建数据库环境
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();}}
- 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类
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 必须提供公共的setter和getter方法
- 一般像这种JavaBean的类都会放在domain等的包下面
功能:封装数据
概念
- 成员变量
- 属性: setter和getter截取后的产物,例如: getUsername()—>Username(下一步变小写)–>username,这里的username一般就是成员变量的名字
这里是通过通过传入的字符串和方法名截取后的产物进行比对,找到正确的方法,来设置属性值或者得到属性值
方法
- setProperty()—>给属性赋值
- getProperty()---->得到属性的值
- 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.设置响应行
- 格式: http/1.1 200 ok
- 设置状态码:
setStatus(int sc)
2.设置响应头
setHeader(String name,String value);
3.设置响应体
使用步骤:
获取输出流
使用输出流,将数据输出到客户端浏览器
案例之完成重定向
重定向: 资源跳转的方式
代码演示:
//访问Demo1资源,自动跳转到Demo2资源//1.设置状态码为302response.setStatus(302);//2.设置响应头locationresponse.setHeader("location","/Demo2Servlet");
简单的重定向写法:
response.sendRedirect("/Demo2Servlet");
重定向和转发的区别和各自特点
路径写法
路径分类
不写默认代表./ ,即当前目录下
动态获取虚拟目录
String contextPath = request.getContextPath();//虚拟目录response.sendRedirect(contextPath+"/Demo2Servlet");
服务器输出字符数据到浏览器
- 获取字符输出流
- 输出数据
代码演示:
//获取字符输出流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>");
服务器输出字节数据到浏览器
- 获取字节输出流
- 输出数据
代码演示:
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="输入图片验证码"> <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);
文件下载案例
文件下载需求:
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
分析:
步骤:
上面说过的响应头相关知识回顾:
代码实现:
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快速入门教程!!!相关推荐
- Servlet快速入门及运行流程
一.Servlet快速入门 1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名 ...
- Day14-HTTP协议 web开发概述 servlet快速入门
HTTP:HyperText Transfer Protocol 超文本传输协议 用于定义web浏览器和web服务器之间交换数据的过程 特点: 基于请求/响应模型的协议.请求和相应必须成对出现,现有请 ...
- BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序
BIML 101 - BIML 快速入门教程 做大数据的项目,最花时间的就是数据清洗. 没有一个相对可靠的数据,数据分析就是无木之舟,无水之源. 如果你已经进了ETL这个坑,而且预算有限,并且有大量的 ...
- HealthKit开发快速入门教程大学霸内部教程
HealthKit开发快速入门教程大学霸内部教程 国内第一本HealthKit专向教程.本教程详细讲解iOS中,如何使用HealthKit框架开发健康应用.最后,本教程结合HealthKit ...
- Apple Watch开发快速入门教程
Apple Watch开发快速入门教程 试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...
- 指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程
指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程 1.4.2 指示灯组 指示灯组的放大图如图1.5所示. 图1.5 指示灯组 各个指示灯对应的功能如下: q RX:对应于0号端口 ...
- 游戏控制杆OUYA游戏开发快速入门教程
游戏控制杆OUYA游戏开发快速入门教程 1.2.2 游戏控制杆 游戏控制杆各个角度的视图,如图1-4所示,它的硬件规格是本文选自OUYA游戏开发快速入门教程大学霸: 图1-4 游戏控制杆各个角度的 ...
- Arduino Yun的主要部件介绍选自Arduino Yun快速入门教程
Arduino Yun的主要部件介绍 1.4.1 主要部件 Yun的主要部件如图1.4所示. 图1.4 Arduino Yun的主要部件 在Yun小小的板子上集成了两颗处理器.一个是ATmega3 ...
- 认识AndEngine选自Android 2D游戏引擎AndEngine快速入门教程
认识AndEngine什么是AndEngine 随着Android手机.平板的盛行,Android下的游戏也不断的变得火热.而对于游戏开发有兴趣的同学们,应该也想要学习开发游戏.虽说游戏开发的引擎较多 ...
最新文章
- 没项目经验,如何砍下字节算法岗40万offer
- Openssl自签名证书
- centos5.8 安装配置vsftp虚拟用户
- Cissp-【第4章 通信与网络安全】-2021-3-14(543页-560页)
- Boost:使用静态c ++内核语言扩展以进行编译和 执行模板化的c ++内核
- ReentrantLock源码
- Python3常用数据结构
- mysql更新代码_mysql update语句的用法
- Mac中找不到.bash_profile则自己创建.bash_profile文件
- t–sql pl–sql_SQL Server –在T-SQL中使用最低的度量单位
- 路由器总是有信号无网络连接到服务器,路由器信号满格但是没有网络怎么办
- 制作一个含生僻字的矢量字体文件(*.shx)
- android静态动画,Android Lottie动画实战踩坑
- 微信小程序使用建行支付
- 一个传奇玩家的传奇故事
- HBase-14.1-JMX监控实战-hadoop
- (难度:35%)untrusted游戏通关攻略
- 新手怎么开通抖音小店?详细操作步骤分享,建议收藏
- Android车机初体验
- (附源码)springboot音乐播放器小程序 毕业设计 170900
热门文章
- 用键盘打出常用符号的方法
- php rewriterule 规则,如何将一条RewriteCond 对应多个RewriteRule规则
- 超级实习生名企内推实习付费吗?与付费实习有何区别?
- 使用python制作的简易自习室座位预约系统
- div及iframe滚动条固定为最底端
- Java实现英文段落分句,python:对英文段落进行分句(对一段英语进行整句切分,切分句子)...
- 最新的三星android版本是多少,国行三星S7/S7 Edge更新最新安卓8.0系统
- 网络入侵敲响警钟,数据安全不容忽视!
- JavaScript:EventUtil.js
- html域名防盗链,跨域访问和防盗链基本原理(一)