tomcat的下载与安装
tomcat的下载与安装:
https://www.cnblogs.com/KmilyLee/p/9358657.html
解决Tomcat: Can’t load IA 32-bit .dll on a AMD 64-bit platform问题:https://blog.csdn.net/xiaokui_wingfly/article/details/8736142
tomcat的目录结构
- bin:放置可执行文件
- conf:配置文件 server.xml文件中存放服务器的配置信息
web.xml存放项目部署描述符 - lib:存放的是API文件,Servlet的API就存放在lib文件夹中
- logs:存放的是日志文件
- temp:存放临时文件
- webapps:存放所有的web项目,一个文件夹就对应着一个web项目,访问文件夹名时直接在端口号后面添加文件夹名,如:http://localhost:8080/文件夹名,root文件夹无需添加文件夹名可直接访问。项目部署就是将web项目的文件夹拷贝到webapps文件夹下。
一个web项目下有WEB-INF,lib和静态资源组成。lib存放核心类库,WEB-INF存放web项目下的核心文件,WEB-INF中的内容不能被直接访问。 - work:存放运行时产生的文件。
Servlet(Server Applet)
- 定义:狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类。
- Servlet工作过程:浏览器产生请求,Servlet容器加载对应的Servlet并且请求封装为ServletRequest对象,Servlet容器调用对应Servlet容器的service方法,Servlet处理请求,Servlet容器解析ServletResponse并将结果返回给浏览器。
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
- Servlet层次结构
Servlet是个接口,实现它时需要实现5个方法,GenericServlet实现了其中的四个方法,只有一个service方法需要自己实现。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
}
public void destroy() {
}
public String getInitParameter(String name) {
return this.getServletConfig().getInitParameter(name);
}
public Enumeration<String> getInitParameterNames() {
return this.getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
public String getServletInfo() {
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public void log(String message) {
this.getServletContext().log(this.getServletName() + ": " + message);
}
public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
public String getServletName() {
return this.config.getServletName();
}
}
HttpServlet继承了GenericServlet
package javax.servlet.http;
public abstract class HttpServlet extends GenericServlet {
public HttpServlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_get_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_post_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
} catch (ClassCastException var6) {
throw new ServletException(lStrings.getString("http.non_http"));
}
this.service(request, response);
}
}
HttpServlet重写并且重载了service方法,在servlet容器调用service方法时,先调用重写的service方法,重写的service方法又调用了重载的service方法,而重载的service又调用了doGet(),doPost()等方法,因此我们只需要重写doGet(),doPost()等方法。
- Servlet的访问
Servlet放在WEB-INF的classes文件夹下,不可通过链接直接访问。需要配置映射,将Servlet的访问映射为链接的访问。有两种方式:
配置web.xml文件:
<!-- 添加节点 -->
<servlet>
<servlet-name>hs</servlet-name>
<servlet-class>servlet.MyHttpServlet</servlet-class>
<load-on-startup>-1</load-on-startup>
</servlet>
<!-- 将链接映射为servlet -->
<servlet-mapping>
<servlet-name>hs</servlet-name>
<url-pattern>/hs</url-pattern>
</servlet-mapping>
匹配方式:
精确匹配:/具体名称
通配符匹配:*.xxx匹配以xxx结尾的链接
匹配所有:/*
匹配不包含jsp的所有请求:/
设置加载顺序:load-on-startup
值为-1或者不设置:启动服务器时不加载,访问时加载
值大于等于0:启动时加载,值越小越先加载
使用注解:
@WebServlet(name = "hs", value = {"/hs"}, loadOnStartup = 0)
name:指定servlet的名字
value:设置url,可替换为urlPatterns,作用与value相同但不能同时使用
loadOnStartup:设置启动时加载Servlet的顺序
5. HttpServletRequest和HttpServletResponse
HttpServletRequest主要方法:
getParameter | 读取对应键的值 |
---|---|
setCharacterEncoding | 设置读取流文件时的编码方式 |
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
HttpServletResponse主要方法:
setHeader(name,value) | 设置响应头 |
---|---|
setContentType(String) | 设置响应文件类型,响应文件编码 |
setCharacterEncoding(String) | 设置服务器端响应内容编码格式 |
getWriter() | 获取字符输出流 |
- 乱码问题的解决
产生乱码的原因:默认情况下,客户端以utf-8编码发送数据,服务器端的request使用ISO8859-1接受数据;服务器端的response使用ISO8859-1发送数据,而客户端使用GB2312接收数据。
解决方法:
接收数据时 | 将接收的数据按ISO8859-1转化为字节流,再将字节流以utf-8的形式编码或者设置request的编码方式为utf-8 |
---|---|
发送数据时 | 设置response的编码方式为utf-8并且通知客户端也以utf-8的形式接收数据 |
/*.....接收数据......*/
//第一种方式
String name = req.getParameter("name");
name = new String(name.getBytes("ISO8859-1"),"utf-8");
//第二种方式
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
/*.....接收数据......*/
//第一种方式
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
//第二种方式
resp.setHeader("Content-type","text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
- 转发和重定向
req.getRequestDispatcher("/login.html").forward(req,resp);
转发由服务器实现,转发实现web应用内的跳转,转发是实现请求的转发。在同一次请求中,HttpRequest对象在多次转发后仍然能够访问。
resp.sendRedirect("http://baidu.com");
重定向由客户端实现,服务器端将请求的链接发送给客户端,客户端重新访问对应的网站。重定向时服务器端只能返回重定向的链接,想要传输数据时只能在链接的末尾添加信息。
- 状态管理
request | 只在一次请求中有效 |
---|---|
cookie | 存放在客户端,可以设置有效时间 |
session | 一次会话中有效,一次会话指的是同一浏览器发送的多次请求,浏览器关闭则这次会话结束 |
ServletContext | 服务器启动中有效,作用于整个web应用 |
cookie的工作过程:服务器创建cookie并通过响应返回给客户端,客户端将cookie存储起来,下一下发送请求时将cookie发送给服务器。
/*......cookie的创建......*/
//创建cookie
Cookie cookie = new Cookie(String, String);
//设置cookie访问路径
cookie.setPath(String);//cookie只有指定访问路径的资源才能访问
//设置cookie的生存时间
cookie.setMaxAge(int);//小于0表示内存存储;等于0浏览器打开;大于0指定生存时间单位为秒
//添加cookie
response.addCookie(cookie);
/*.......cookie的获取.....*/
Cookie[] cookies = request.getCookies();
//获取属性名
cookie.getName();
//获取值
cookie.getValue();
/*......修改cookie........*/
Cookie cookie = new Cookie(String, String);
cookie.setPath();
responset.addCookie(cookie);
cookie的属性名和路径相同的情况下会替换值
/*........Cookie的编码与解码.......*/
//cookie使用的是ASCII码,直接传送会产生乱码
Cookie cookie = new Cookie(URLEncoder.encode(String), URLEncoder.encode(String));
String s1 = (String) URLDecoder.decode(cookie.getName());
String s2 = (String) URLDecoder.decode(cookie.getValue());
session的工作过程,如果浏览器是第一次访问某个web应用,web应用会自动创建一个session保存相关的信息,并且创建一个键为“JSESSIONID ”值为“…”的cookie返回给浏览器,浏览器存储cookie,下次访问这个web应用时会将cookie发送给服务器,服务器通过JSESSIONID来查找对应的session。随着浏览器的关闭,cookie会自动消失,也就是说setMaxAge(0)。
/*............session的获取..........*/
HttpSession session = request.getSession();
//存值
session.setAttribute(String, Object);//可以存任何对象,cookie只能存字符串
//取值
session.getAttribute(String);
//删除属性
session.removeAttribute(String);
//设置有效期
session.setMaxInactiveInterval(int);
//设置session失效
session.invalidate();
/*...........URL重定向..........*/
//用户禁用cookie时浏览器无法获取JSESSIONID,在重定向时可以通过向链接的末尾加入JSESSIONID来解决
//重写链接
String newURL = response.encodeRedirectURL("/...");
response.sendRedirect(newURL));
ServletContext:整个web应用的上下文。
/*.........ServletContext的获取方法..........*/
Servlet context = this.getServletContext();
Servlet context = request.getServletContext();
HttpSession session = req.getSession();
Servlet context = session.getServletContext();
//获取项目真实路径
context.getRealPaht("/");
//获取相对路径
context.getContextPath();
//存储数据
context.setAttribute(String, Object);
//访问数据
context.getAttribute(String);
//删除数据
context.removeAttribute(String);
- 过滤器
客户端发送请求,过滤器拦截请求,处理完后放行给对应的资源,资源处理完后将结果发送给过滤器,过滤器处理完后返回给客户端。
/*..............实现Filter接口..............*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//拦截前的操作
System.out.println("filter before");
//放行
filterChain.doFilter(servletRequest, servletResponse);
//拦截后的操作
System.out.println("filter after");
}
@Override
public void destroy() {}
}
配置拦截对象
<filter>
<filter-name>myfilter</filter-name>
<filter-class>filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<!--要拦截的目标资源而不是filter的访问路径-->
<!--*.xxx:匹配特定后缀的资源;/*匹配所有资源;/aaa/*:拦截aaa下的所有-->
<url-pattern>/target</url-pattern>
</filter-mapping>
配置注解时使用的是@WebFilter(value = “/target”)
使用xml文件配置是,先配置的过滤器先执行,使用注解配置时根据filter的类的全名称的字母顺序执行,xml配置高于注解配置,如果同时配置xml和注解则会创建多个对象。