Servlet总结
第一章:JavaEE概述
1.什么是javaEE?
javaEE是一个开发分布式企业级应用的规范和标准
2.javaME:手机开发
javaSE:标准版(java核心类,集合,jdbc,IO,网络编程),适用于桌面系统的开发
javaEE:企业版(javaSE,Servlet,ejb) 开发分布式企业应用标准和规范
3.快捷键:
ctrl+1 提示操作
ctrl+D 删除当前行
ctrl+shift+O 组织导包
ctrl+shift+M 单独导包
ctrl+M 最大化当期窗体
Alt+Shift+R 重命名 ctrl+shift+F 格式化当前文本
ctrl+shift+F4 关闭当前打开的所有文件
4.获得站点的根路径:request.getContextPath(); 在指定图片的路径和response.sendRedirect()时经常
5.JavaEE体系结构分为表示层、中间层、数据层
三层功能:
表示层:由用户界面和用于生成界面的代码组成
中间层:包含系统的业务和功能代码
数据层:负责完成存取数据库的数据和对数据进行封装
三层技术:
表示层:HTML、JavaScript、Ajax
中间层:JSP、Servlet、JSTL、JavaBean、框架技术(Struts:Struts主要是扩展了Servlet)
数据层:JDBC、数据库框架技术(Hibernate:提供了以对象的形式操作关系型数据库数据的功能)
6.表单的两种提交方式区别:
GET提交数据在地址栏内显示,不安全;而POST不显示,相对安全
GET提交数据量有限制(255个字符);而POST没有
GET请求的页面可以设置为书签或使用邮件发送;而POST不可以
7.HTTP协议是无状态协议,当浏览器向服务器发送一个请求后,服务器对该请求做出响应,当响应结束后,就断开连接,彼此并不保持连接信 息。当下次请求时,服务器能够区分是哪一个用户是通过存储在客户端Cookie中的sessionID
8.三层好处:
一个组件的更改不会影响其他两个组件。
由于表示层和数据层相互独立,因而可以方便地扩充表示层,是系统具有更好的扩展性。
代码重复减少。
方便分工和协作。不同的小组能够独立地开发应用程序的不同部分,并充分发挥各自的长处和优势
缺点:效率相对不高
第二章:Servlet基础
1.什么是Servlet
Servlet是在服务器端运行以处理客户端请求并作出响应的程序(页面和模型层的中介)
2.Servlet中实现向浏览器中输出指定内容
PrintWriter out=response.getWriter();
out.println("<html>");
3.为了客户端无论使用什么方法提交请求程序都能正确地接收到数据,把处理代码都写在doGet()方法中,之后在doPost()方法中调用doGet()方法
4.Servlet生命周期
加载和实例化:当客户端发送一个请求时,Servlet容器(Tomcat)会查找内存中是否存在Servlet实例,如果不存在,就创建一个Servlet实例。如果存在Servlet实例,就直接从内存中取出该实例来响应请求。
初始化:初始化Servlet时,可以设置数据库连接参数,建立JDBC连接,或是建立对其他资源的引用。初始化阶段,init()方法被调用。
服务:Servlet初始化后,就处于响应请求的就绪状态。
销毁:销毁由容器完成,销毁调用Servlet的destroy()方法。
5.重定向:response.sendRedirect("/show.jsp"); 在浏览器中地址为:http://localhost:8080/show.jsp
请求转发:request.getRequestDispatcher("/login.jsp").forward(request,response);在浏览器中地址为:http://localhost:8080/f0806/login.jsp
6.中文乱码问题
get 提交
String name = request.getParameter("name");
new String(name.getBytes("ISO-8859-1"),"UTF-8");
post 提交
request.setCharacterEncoding("UTF-8")
页面编码:
1.pageEncoding="UTF-8" 源文件编码
2.contentType="text/html;charset=utf-8" 响应编码
contentType="image/jpeg"
3.浏览器编码
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
第三章:基于Servlet的会话跟踪(一)
1.在Web项目中使用session,是为了跟踪用户状态,并区分不同的用户
2.会话是Web容器创建的,而不是程序员创建的。当客户端浏览器第一次访问服务器的时候,服务器为客户端创建一个session
3.session结束有3种方式
●浏览器关闭。
●两次访问的间隔时间大于非活动时间(超时)。
●调用HttpSession的invalidate()方法。
在session结束时,服务器会清空当前浏览器相关的数据信息
4.HttpSession用setAttribute()保存数据,用getAttribute()获取数据
5.设置session超时
●代码中 session.setMaxInactiveInterval(60*60*2) 超时两小时
●web.xml
<session-config>
<session-timeout>30分钟</session-timeout>
</session-config>
6.创建会话(在购物车时经常用到)
HttpSession session=request.getSession(boolean value);
HttpSession session=request.getSession();
第一种方法,布尔值为true时,如果存在与当前会话关联的会话,就返回该会话,否则创建一个新的会话,并把该会话返回。
布尔值为false时,如果存在与当前请求关联的会话,就返回该会话,否则返回null,不创建新的会话
第二种方法等同于第一种方法中布尔值为true的情况
7.获取application对象
ServletContext application=this.getServletContext();
第四章:基于Servlet的会话跟踪(二)
1.购物车可以使用(List、Map、Set) ,但最好使用Map,因为查找数据方便
Map 的方法:put(key,value)、 object get(key)、Collection values()
2.Java中常用的集合接口有List、Set和Map
●常用的List接口的实现类有ArrayList类、LinkedList类
●常用的Set接口的实现类有HashSet
●常用的Map接口的实现类有HashMap类、Properties类
3.设置价格格式
<%@ page import="java.text.*"%>
price=book.getPrice();
<%=new DecimalFormat("0.00").format(price)%>
4.在Servlet中获取当前提交页面的名称(使用过滤器时用到)
String path=request.getServletPath();
if(path.equals("/login.jsp") ){
chain.doFilter(req,res);
}
第五章:基于Servlet的MVC设计模式
1.什么时设计模式?
设计模式是一套反复使用、成功的代码设计经验的总结。
2.MVC的三个模块
模型(Model):对应的组件是JavaBean(Java类)。
视图(View):对应的组件是JSP或HTML文件。
控制器(Controller):对应的组件是Servlet。
第六章:高级JDBC
1.数据库连接的三种方式:
● 编码方式,把数据库配置信息直接写入Java代码中。
● .properties文件,把数据库配置信息写在属性文件中,用程序读取。
● 数据源,使用JNDI来获取DataSource对象,从而得到Connection对象。
2.为什么要使用数据库连接池?
数据库连接是非常占用系统资源的,为了提高应用程序的性能,优化数据库的连接,出现了数据库连接池。
3.什么是JNDI?
JNDI是将对象和名字绑定的技术,容器生产出对象,这些对象都和唯一的名字绑定。外部程序都可以通过名字来获得该对象。
4.JNDI配置
● 如果想用全局配置,在tomcat的context.xml中配置
● 如果只想在某个项目中用,在META-INF下新建一个context.xml
第一步:在context.xml中
<Context reloadable="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/books" auth="Container"
type="javax.sql.DataSource" maxActive="100" maxIdle="30"
maxWait="10000" username="sa" password="123"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;DataBaseName=books"
/>
</Context>
reloadable="true" 表示该xml内容改动后,重新加载该xml
<WatchedResource>WEB-INF/web.xml</WatchedResource>监听web.xml是否改动,如果改动,重新加载web.xml
第二步:在web.xml中
<web-app>
<resourc-ref>
<description>E-Books DataSource</description>
<res-ref-name>jdbc/books</res-ref-name>
<res-type>javax.sql.DataSource</res-type> --->一定要在<res-auth>之前
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
第三步:将数据库驱动拷贝到tomcat的common\lib下面
第四步:
代码中获取数据库连接
import java.sql.*;
import java.naming.Context;
import java.naming.InitialContext;
import javax.naming.NamingException;
import java.sql.DataSource;
public class DBManager{
public Connection getConn(){
Connection conn=null;
try{
Context ic = InitialContext();
DataSource source=(DataSource) ic.lookup("java:comp/env/jdbc/books");
conn=source.getConnection();
}catch(NamingException e){
e.printStackTrace();
}
return conn;
}
}
5.属性文件的数据库配置(.properties文件形式只能保存String类型信息)
第一步:
在项目默认路径(src)下创建文件,名称为db.properties(名称可自定以,后缀名不行)
在db.properties中写入如下内容
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://localhost:1433;DatabaseName=books
user=sa
password=sa
第二步:
import java.io.InputStream;
import java.util.Properties;
public class Env extends Properties {
private static Env instance;
//只创建一个实例
public static Env getInstance() {
if (instance != null)
return instance;
else {
makeInstance();
return instance;
}
}
//同步方法,保证在同一时间,只能被一个人调用
private static synchronized void makeInstance() {
if (instance == null) {
instance = new Env();
}
}
private Env() {
InputStream is = getClass().getResourceAsStream("/db.properties");//加载db.properties文件
try {
load(is);//取得属性列表
} catch (Exception e) {
System.err.println("错误:没有读取属性文件,请确认db.property文件是否存在");
}
}
}
第三步:
public static synchronized Connection getConn(){
String driverClassName = Env.getInstance().getProperty("driver");
String url = Env.getInstance().getProperty("url");
String user = Env.getInstance().getProperty("user");
String password = Env.getInstance().getProperty("password");
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception ex) {
ex.printStackTrace();
}
return conn;
}
6.自定义异常:在编写程序时,由于错误信息位置不够具体和准确,从而不能很快找到错误,所以需要自定义异常
public class MyException extends Exception {
protected Exception throwable;
public MyException(){
super();
}
public MyException(String message){
super(message);
}
public MyException(String message,Exception throwable){
super(message);
this.throwable=throwable;
}
public Exception getCause(){
return throwable;
}
}
使用自定义异常
public static synchronized Connection getConn() throws MyException{
String driverClassName = Env.getInstance().getProperty("driver");
String url = Env.getInstance().getProperty("url");
String user = Env.getInstance().getProperty("user");
String password = Env.getInstance().getProperty("password");
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception ex) {
throw new MyException("获取数据库连接失败");
}
return conn;
}
第七章:标准动作
1.JavaBean 要满足一下要求三个要求
→是一个公有类,并提供无参的公有的构造方法
→属性私有
→具有公有的访问属性的getter和setter方法
2.JSP标准动作
● jsp:useBean 动作用来装载一个将在jsp页面上使用的JavaBean,相当于创建了一个对象
<jsp:useBean id="name" class="package.class" scope="scope">
scope的值
page JavaBean只能在当前页面中使用。当加载新页面时就会将其销毁。
request JavaBean在用户对其发出请求时存在。
session JavaBean一直存在会话中,直至其终止或被删除为止。
application JavaBean在整个应用程序中均可使用。
例:<jsp:useBean id="order" class="y2javaee.sg.ch07.order" scope="request">
● jsp:setProperty 动作用于设置useBean中指定的JavaBean的属性值。
<jsp:setProperty name="BeanName" property="PropertyName" value="Value" param="Parameter">
name 为useBean中使用的JavaBean的id,property 为要设置值的JavaBean的属性名称
如果property和param的名字一样,则可用<jsp:setProperty name="BeanName" propertyName="*"> 代替
例:<jsp:setProperty name="order" property="username" value="accp">
● jsp:getProperty 动作获取JavaBean中指定的属性值
<jsp:getProperty name="beanName" property="propertyName">
name 为useBean中使用的JavaBean的id,property为要获取值的JavaBean的属性名称
例:<jsp:getProperty name="order" property="username">
● <jsp:include page="head.jsp" /> 动态包含 将运行后的结果包含的指定的页面。
<%@ include file="head.jsp" %> 静态包含 将页面的源代码包含到指定的页面。
● <jsp:forward page="/url"><jsp:param name="参数名" value="参数值"/></jsp:forward>
<jsp:forward>实质是使用RequestDispatcher对象的forward方法实现转发的
在浏览器中地址为:http://localhost:8080/webapps/...
第八章:EL和JSTL
1.EL表达式是为了解决JavaBean中的属性是对象时的读取
2.在EL表达式中获取应用程序的根路径 ${pageContext.request.contextPath()}
获取session的Id ${pageContext.session.id}
3.EL隐式对象
${param.name} 相当于request.getParameter("name");
${paramValues.name} 相当于request.getParameterValues("name");
${param.name} 如果没有值,输出“”,不会是null
pageContextScope、requestScope、sessionScope、applicationScope
4.${empty param.loginName} 判断表单提交的loginName是否为空或“” 如果为空,则为true
例:
<c:if test="${!empty requestScope.detailsInfo}">
<c:set var="foodDetail" value="${requestScope.detailsInfo}" />
</c:if>
5.如果在标准动作中定义的变量,可以在EL表达式中可以直接访问到。
在小脚本中或者servlet中定义的变量则必须通过域才能访问${requestScope.num}
如果${num},则程序从前往后找不同域中是否有num,找到后,则不往下找,一般取数据时要指定域
6.JSTL:解决 java 脚本的逻辑判断
通用标签:set、remove、out
核心标签库: 条件标签:if
迭代标签:forEach
SQL标签库:update、param、query
使用JSTL标签
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="example" value="${100+1}" scope="session">
<c:out value="${example}">
<c:remove var="example" scope="session">
<c:out value="value" default="100"> 当值不存在时,输出100
<c:out value="${<a href='ww.baidu.com'>test</a>}" escapeXml="false"> 输出为一个链接
<c:if test="${!empty requestScope.detailsInfo}"></c:if>
多分支:
<c:choose>
<c:when test="条件运算">
....
</c:when>
<c:when test="条件运算">
....
</c:when>
<c:otherwise>
....
</c:otherwise>
</c:choose>
<c:forEach item="${sessionScope.bookTitles}" var="currentBook" varStatus="status"></forEach> varStatus="status"相当于for中的i变量
<c:forEach var="j" begin="1" end="10" step="2"></forEach> 输出1、3、5、7、9
7.SQL标签使用
增、删、该
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<sql:setDataSource driver="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;DatabaseName=restrant" user="sa"
password="sa" var="conn"/>
<sql:update var="order" dataSource="${conn}">
insert into foodOrderInfo values(?,?,?,?,?,?,?)
<sql:param value='${param["name"]}'/>
<sql:param value='${param["addr"]}'/>
<sql:param value='${param["zip"]}'/>
<sql:param value='${param["tel"]}'/>
<sql:param value='${param["mov"]}'/>
<sql:param value='${param["bz"]}'/>
<sql:param value='${sessionScope.total}'/>
</sql:update>
<c:if test="${order==1}">
<% session.removeAttribute("food"); %>
<c:redirect url="/seeYou.jsp"/>
</c:if>
查
<sql:setDataSource driver="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;DatabaseName=restrant" user="sa"
password="sa" var="conn"/>
<sql:query var="rs" dataSource="${conn}">
select * from foodOrderInfo
</sql:query>
<c:forEach var="row" items="${rs.rows}">
<tr>
<td>${row.customerName }</td>
<td>${row.address }</td>
<td>${row.zipCode }</td>
<td>${row.telephone }</td>
<td>${row.movePhone }</td>
<td>${row.notice }</td>
<td>${row.totalPrice }</td>
</tr>
</c:forEach>
8.格式化标签:
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
格式时间:
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd hh:mm:ss"/>
格式数值:
<fmt:formatNumber value="100000" type="currency" ></fmt:formatNumber>
9. 函数标签:
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
${fn:toUpperCase('abc')}
第九章:Web服务
1.使用XFire创建和发布Web服务的步骤如下。
● 添加XFire库
● 添加XFire-all-1.2.6.jar包
● 创建服务接口和实现类
● 配置servies.xml文件
● 配置web.xml文件
● 添加xalan.jar包,测试web服务是否正常工作
● 创建客户端程序访问Web服务
2.web.xml
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
3.在META-INF文件夹下新建services.xml
<service>
<name>CreditCard</name>
<namespace>www.sss.com.cn</namespace>
<serviceClass>
y2javaee.sg.ch09.IProcessCredit
</serviceClass>
<implementationClass>
y2javaee.sg.ch09.ProcessCreditCard
</implementationClass>
</service>
4.public int ramGain() {
Service serviceModel = new ObjectServiceFactory().create(Iweather.class);
XFire xfire = XFireFactory.newInstance().getXFire();
XFireProxyFactory factory = new XFireProxyFactory(xfire);
String url = "http://localhost:8080/restrant/services/weatherService";
Iweather client = null;
try {
client = (Iweather) factory.create(serviceModel, url);
} catch (Exception e) {
System.out.println("客户端调用异常" + e.toString());
}
int num = 0;
try {
num = client.getRanNum();
} catch (Exception e) {
System.out.println("获取随机数错误" + e.toString());
}
return num;
}
5.单元测试JUnit4 :优点是不再需要将所有的方法命名为 testFoo()、testBar(),等等
import org.junit.Test;
import junit.framework.TestCase;
public class AdditionTest extends TestCase {
private int x = 1;
private int y = 1;
@Test public void testAddition() {
int z = x + y;
assertEquals(2, z);
}
}
只要用 @Test 来注释测试方法,就可以将测试方法放到任何类中。但是您需要导入 junit.Assert 类以访问各种 assert 方法,如下所示:
import org.junit.Assert;
public class AdditionTest {
private int x = 1;
private int y = 1;
@Test public void addition() {
int z = x + y;
Assert.assertEquals(2, z);
}
}
您也可以使用 JDK 5 中新特性(static import),使得与以前版本一样简单:
import static org.junit.Assert.assertEquals;
public class AdditionTest {
private int x = 1;
private int y = 1;
@Test public void addition() {
int z = x + y;
assertEquals(2, z);
}
}
在 JUnit 4 中,您仍然可以在每个测试方法运行之前初始化字段和配置环境。然而,完成这些操作的方法不再需要叫做 setUp(),只要用 @Before 注释来指示即可,如下所示:
@Before protected void initialize() {
System.setErr(new PrintStream(new ByteArrayOutputStream()));
inputDir = new File("data");
inputDir = new File(inputDir, "xslt");
inputDir = new File(inputDir, "input");
}
在 JUnit 4 用 @After 代替 JUnit3 中的tearDown()
@After protected void disposeDocument() {
doc = null;
System.gc();
}
测试异常
异常测试是 JUnit 4 中的最大改进。旧式的异常测试是在抛出异常的代码中放入 try 块,然后在 try 块的末尾加入一个 fail() 语句。例如,该方法测试被零除抛出一个 ArithmeticException:
public void testDivisionByZero() {
try {
int n = 2 / 0;
fail("Divided by zero!");
}
catch (ArithmeticException success) {
assertNotNull(success.getMessage());
}
}
该方法不仅难看,而且试图挑战代码覆盖工具,因为不管测试是通过还是失败,总有一些代码不被执行。在 JUnit 4 中,您现在可以编写抛出异常的代码,并使用注释来声明该异常是预期的:
@Test(expected=ArithmeticException.class)
public void divideByZero() {
int n = 2 / 0;
}
补充:
1.过滤器:设置网页编码的过滤器
● Servlet 中
public class EncodingFilter extends HttpServlet implements Filter {
private String charset=null;
public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding(charset);
res.setCharacterEncoding("GBK");
chain.doFilter(req, res);
}
public void init(FilterConfig config) throws ServletException {
charset=config.getInitParameter("charset");
if(charset==null)
charset="GBK";
}
}
● web.xml文件中
<filter>
<filter-name>Encoding</filter-name>
<filter-class>web.EncodingFilter</filter-class>
<init-param>
<param-name>charact</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.监听器:获取数据库连接和关闭数据库连接
●Servlet 中
public class ContextListener extends HttpServlet implements ServletContextListener {
public void contextDestroyed(ServletContextEvent sce) {
DBManager.closeConnection();
}
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
String driver = context.getInitParameter("driver");
String url = context.getInitParameter("url");
String user = context.getInitParameter("user");
String password = context.getInitParameter("password");
DBManager.getConn(driver, url, user, password);
}
}
●web.xml中
<context-param>
<param-name>driver</param-name>
<param-value>com.microsoft.sqlserver.jdbc.SQLServerDriver</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:sqlserver://localhost:1433;DatabaseName=restrant</param-value>
</context-param>
<context-param>
<param-name>user</param-name>
<param-value>sa</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>sa</param-value>
</context-param>
<listener>
<listener-class>web.ContextListener</listener-class>
</listener>
3. 判断用户是否登录的Servlet
public class IsLogin extends HttpServlet implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String path = request.getServletPath();
String pathFormate = path.substring(path.lastIndexOf(".") + 1,path.length()).toLowerCase();
//如果是以下条件,不需要判断是否已经登录
if (path.equals("/ch07/checkLogin.jsp") || path.equals("/ch07/checkOut.jsp") || path.equals("/ch07/login.jsp")
|| path.equals("/ch07/middle.jsp") || path.equals("/ch07/show.jsp") || pathFormate.equals("css")
|| path.equals("/login.jsp") || path.equals("/LoginServlet") || pathFormate.equals("gif")
|| pathFormate.equals("jpg") || pathFormate.equals("js")) {
chain.doFilter(req, res);
} else {
HttpSession session = request.getSession(false);
if (session != null) {
if (session.getAttribute("login") == null) {
response.sendRedirect(request.getContextPath()+ ("/login.jsp"));
return;
} else {
chain.doFilter(req, res);
}
} else {
response.sendRedirect(request.getContextPath() + ("/login.jsp"));
return;
}
}
}
web.xml中
<filter>
<filter-name>IsLogin</filter-name>
<filter-class>web.IsLogin</filter-class>
</filter>
<filter-mapping>
<filter-name>IsLogin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.Servlet 中下载
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
HttpSession session = request.getSession();
Cart cart = null;
if (session.getAttribute("food") != null) {
cart = (Cart) session.getAttribute("food");
CreateExcel.createXls(cart.getAllCart());
// 新建一个SmartUpload对象
SmartUpload su = new SmartUpload();
// 初始化
su.initialize(null);
// 设定contentDisposition为null以禁止浏览器自动打开文件
su.setContentDisposition(null);
try {
su.downloadFile("c:\\1.xls");
} catch (SmartUploadException e) {
e.printStackTrace();
}
}
}