一. eclipse创建web工程
- 新建工程
- 添加flod文件夹,命名WEB-INF
- WEB-INF中添加classes文件夹、lib文件夹和web.xml文件
- 修改字节码文件输出路径为WEB-INF/classes。项目-属性-Java Build Path-source
(一)intellij idea 创建web工程
- new project-java-java EE-webapplication,填写项目名
- 右键项目名,open module setting- sources选择WEB-INF 快捷键commadn+N 新建文件夹classes和lib;Paths输出路径为新建的classes;dependencies “+” -1 jar-lib文件夹,“+”-2library 选择tomacat包
- tomcat配置。 run-edit configurations- ‘+’-选tomcat-local,
server标签页第一次需要导入tomcat路径,之后不需要。Deployment-"+" 添加工件,application context可以添加上下文名称,回到server标签页,on "update" action和 on frame deactivation 都选update classes and resource,
有时端口被占用,改下2个端口号
二. HTTP协议
- 规定数据传输格式。
- HTTP1.0规范,多次请求资源,需建立多次连接,发送多次请求和接收多次响应,关闭多次连接。
- HTTP1.1规范,一次连接可以多次请求和响应,一次关闭。
- HTTP消息结构:一个请求行、若干请求头和实体内容,一些请求头和实体内容可选,后2者之间用空行隔开
<1>Accept:mime类型
<2>Accept-Charset:支持的字符集
<3>Accept-Encoding:编码方式
<4>Accept-Language:支持的语言
<5>Referer:当前页面由哪个页面访问过来
<6>Content-Type:请求正文的mime类型
<xxx>
三. Helloservlet
- 右键项目中src文件夹,新建包
- 右键新建的包,新建java类文件
- 新建的公共类继承HttpServlet 报错,根据提示导入包,再导入接口的抽象方法
四. Servlet请求流程
- 浏览器发送请求,地址链接http://主机ip/上下文路径/资源名称
- 服务器解析,从server.xml中找到上下文路径匹配的Path,当前项目根路径下/WEB-INF 找到web.xml,找到和资源名称匹配的Servlet类的全限定名称,有个映射过程。
- 反射机制创建Servlet对象
Servlet obj = Class.forName("全限定类名").newInstance();
- 创建ServletConfig对象,使用Servlet对象调用init方法,
obj.init(config);
- 创建req和resp对象,并调用service方法,
obj.service(req,resp);
- 在service方法中给浏览器做响应
特点:非第一次请求过程,步骤1,2后,http无状态,但是有缓存,故可从Servlet实例池中取出Servlet对象,5,6
五. 表单输入,后台乱码问题
首选解决方法:在Run-Edit configurations-Startup/Connection 中Run中添加environment variables
JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8.
- 表单方法为post时,可以在获取参数之前设置字符编码格式
req.setCharacterEncoding("UTF-8");
但是必须在获取所有参数中任意一个参数的语句之前
- 表单方法为get时,目前测试没问题,有问题的话是因为默认编码格式是ISO-8859-1,先获取参数,然后用该格式解码,再用UTF-8格式编码
String age = req.getParameter("age");
byte[] data = age.getBytes("ISO-8859-1");
age = new String(data,"UTF-8");
(eclipse)或者修改tomcat的配置文件server.xml,修改其中端口那一行
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改为
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
URIEncoding="UTF-8"
URIEncoding缺省情况下,为"ISO-8859-1"的编码格式
六. 配置文档和注解
- 配置文档
<?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_3_1.xsd" version="3.1" metadata-complete="false">
<!--是否忽略注解-->
<servlet>
<servlet-name>MappingServlet</servlet-name>
<servlet-class>com.txm._01_mapping.MappingServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MappingServlet</servlet-name>
<url-pattern>/map2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MappingServlet</servlet-name>
<url-pattern>/map1</url-pattern>
</servlet-mapping>
</web-app>
- 注解
@WebServlet(value="/map",loadOnStartup = 0,initParams = @WebInitParam(name="encoding",value="UTF-8"))
- 比较
(1). 从开发角度:注解简单
(2). 从维护角度上:注解维护困难,使用注解又把硬编码再次拉回到代码中
开发中:通用配置一般使用xml完成,维护性好,清晰,特殊配置,使用注解。
在web中,和其他框架做集成,就只能用配置方式。
七. Servlet线程不安全问题
Servlet优点:动态网页,跨平台的,单例的(速度快)
缺点:多线程并发Servlet线程不安全,输出界面不友好
根本原因:多个线程并发访问同一份资源
解决方案:不要使用成员变量,单例情况下,若网络延迟,成员变量赋值再读取,可能读到的不是自己赋的值。
八. Cookie,客户端共享数据的技术,参数传递,会话跟踪。
- 作用把需要共享的信息,保留在客户端(浏览器)中。不同于在链接中直接传递参数,信息出现在地址栏,不安全。但是依然可以利用开发工具查看set-Cookie信息。
- 语法
当前回话需要设置cookie,响应添加cookie,此次回话过程中,访问只要获取cookie,响应不需要再次添加cookie。
//LoginServlet.java
Cookie c = new Cookie("username",username);
resp.addCookie(c);
//ListServlet.java
Cookie[] c = req.getCookie();//获取的是Cookie数组
String username = c[i].getValue();
- Cookie不支持中文和安全性
利用加密和解密方式,同时解决上诉两个问题
//LoginServlet.java
Cookie c = new Cookie("name", URLEncoder.encode(username,"UTF-8"));
req.addCookie(c);
//ListServlet.java
Cookie[] c = req.getCookie();//获取的是Cookie数组
String username = URLDecoder.decode(c[0].getValue());
- Cookie 路径和域
整个应用可用 c.setPath("/");
多个二级域名可用c.setDomain(".baidu.com");
九. Session服务器端的数据共享技术,不使用会话跟踪
- 服务器器开辟一个空间存储客户端信息,响应时传回这个Session的id给浏览器,浏览器下次访问时,再传回这个id,用于识别认证,服务器就可以根据这个id取出数据。
- 操作
//1.获取或创建session
HttpSession session = req.getSession();
//2.把共享数据存储在Session中,键值对形式
//session.setAttribute(String name, Object value);
session.setAttribute("username","will");
//3.从session中取出共享数据
Object val = session.getAttribute("username");
//4.修改session中的共享数据
//重新设置一个同名的属性名
session.setAttribute("username","tom");
//5.删除知道属性值
session.removeAttribute("username");
//6.拓展
User user = new User("name","password");
session.setAttribute("User_in_Session",user);//习惯名字为"XXX_In_Session"
/*习惯把放入Session的对象(User类),让它实现序列号接口,则当多台服务集群的时候,彼此之间可以共享session数据。序列化,对象转为二进制,反序列化则是把二进制数据恢复成对象,二者都是对象流。
*/
. 销毁Session对象(退出,注销登录)
操作中的删除方法只能删除一个指定名称的属性
session.invalidate();销毁整个Session对象
----------------分割线-------------------