目录
1 Web.xml常用信息
在新建Dynamic Web project的项目时选择Dynamic Web module version选择2.5。便于查看web.xml配置信息。
1.1 默认配置
创建完项目后,你会看到如下的web.xml文件:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
它的作用是:访问Web应用时,如果仅给出Web应用的根访问URL,没有指定具体的文件名,容器会调用<weblcome-file- list> 标签里指定的文件。<welcome-file-list>里允许有多个<welcome-file>元素。容器会按顺序寻找,先找第一个文件是否存在,如果存在则会把这个文件显示出来,不再寻找其他文件。如果不存在则寻找第二个文件,依次类推。如果所有文件都不存在,则抛出404错误。
1.2 servlet的xml信息
然后创建一个名叫Hello的servlet文件,web.xml更新如下内容:
<servlet>
<description></description>
<display-name>Hello</display-name>
<servlet-name>Hello</servlet-name>
<servlet-class>it.cast.Hello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
<servlet-name>标签指定此servlet的名字。
<servlet-class>指定servlet的类
<servlet-mapping>标签可定义servlet映射,里面的<servlet-name>要与前面的名字一致,<url-pattern>指定servlet映射的路径。
当 <url-pattern>/Hello</url-pattern>设为‘/’时,用于处理其他页面都不处理的的访问请求。
1.3 其他配置
这些后面才会用到
session的配置
<session-config>
<session-timeout>10</session-timeout>
</session-config>
该数值以分钟为单位。用户访问Web项目时,会与服务器之间建立一个session,当用户长时间未与服务器信息交互而超过这个时长时,服务器会销毁这个session。
filter的配置
<filter>
<display-name>stop</display-name>
<filter-name>stop</filter-name>
<filter-class>it.cast.stop</filter-class>
</filter>
<filter-mapping>
<filter-name>stop</filter-name>
<url-pattern>/stop</url-pattern>
<dispatchar>FORWARD</dispatchar>
</filter-mapping>
就像是servlet的配置,其中<url-pattern>/stop</url-pattern>变成用来指明要拦截的servlet。改为‘/*’可实现全部拦截。
添加<dispatchar>FORWARD</dispatchar>可用于拦截forward()请求。
listener监听器
<listener>
<listener-class>com.channel.http.SessionListener</listener-class>
</listener>
<listener>标签指定监听器,用于监听Web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。
2 response与request的方法
2.1 获取请求参数
html中写一个文本框
<form action="http://localhost:8080/User_homework/jsp_index" method="post">
<div class=sign-3>
<input type="hidden" />
<input class=sign1 type="text" name="music"/>
<input class=sign2 type="submit" value="按我"/></div>
</form>
给<input>设置了name属性后,通过点击提交按钮后,后台通过
String music=request.getParameter("music");
获得你输入的值。
2.2 发送后台参数
对上面的music字段进行改动后,要发送到刚才的前台页面,并将你输入的值设置为后台的值。
String music = "你好吗";
request.setAttribute("music", music);
RequestDispatcher dis=request.getRequestDispatcher("User/index.html");
dis.forward(request, response);
2.3 request 应用
除去上面的方法,它还可以用于获取多个同名的值,应用于多选框
<input type="checkbox" name="hobby" value="dance">跳舞
<input type="checkbox" name="hobby" value="soccer">足球
后台获取为数组
String[] hobby=request.getParameter("hobby");
2.4 response应用
如果你想直接跳转到一个页面,可以用重定向,但这样没有信息:
response.sendRedirect("index.jsp");
一般用response来显示信息
response.getWriter().write("<script language='javascript'>alert('失败,密码错误!');</script>");
response.setHeader("refresh","0.1;url=index.jsp");
弹出密码错误窗口栏,点击确定后0.1秒跳转到index.jsp页面。
或者直接在页面上显示:
response.getWriter().write("Hello MyServlet ");
2.5 请求转发与重定向差别
重定向:其实是两次request, 第一次,客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会丢失。
请求转发:是服务器内部把对一个request/response的处理权,移交给另外一个对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。 传输的信息不会丢失。
2.6 超链接传参
<a class=sign href="http://localhost:8080/User_homework/jsp_person?id=1">
点击超链接后,后台通过
String id=request.getParameter("id");
自然,通过form同上
<form action="http://localhost:8080/User_homework/jsp_sign?id=1" method="post">
3 cookie以及session应用
3.1 cooike应用
首先设置cookie添加我的登陆名和密码,然后要给它们一天的存在时间,最后response发送出来:
String username = request.getParameter("username");
String password = request.getParameter("password");
Cookie usernameCookie = new Cookie("username",username);
Cookie passwordCookie = new Cookie("password",password);
usernameCookie.setMaxAge(24*60*60);
passwordCookie.setMaxAge(24*60*60);
response.addCookie(usernameCookie);
response.addCookie(passwordCookie);
在另一个页面获取,可用于自动登陆。
String username,password;
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length>0)
{
for(Cookie c : cookies)
{
if(c.getName().equalsIgnoreCase("username"))
{
username = c.getValue();
}
if(c.getName().equalsIgnoreCase("password"))
{
password = c.getValue();
}
}
}
3.2 session应用
获取id,存入session
String id = request.getParameter("id");
request.getSession().setAttribute("id", id);
在另一个页面获取
String str=(String) request.getSession().getAttribute("check_code");
3.3 两者的差别
- session是在服务器端保存用户信息,cookie是在客户端保存信息;
- session中保存的是对象,cookie中保存的是字符串;
- session对象随会话结束而结束,cookie可以长期保存在客户端;
- cookie通常用于保存不重要的用户信息,重要的信息使用session保存.session需要借助cookie才能正常工作;
- cookie的数量不同浏览器有不同限制,每个站点可能最多存放20个Cookie,每个Cookie的大小限制为4KB。session无限制,但是过度使用会会造成浏览器资源耗尽。
4 jsp技术及EL,JSTL应用
4.1 运行原理
客户端——>jsp文件——> servlet文件——>class文件——>servlet实例——>客户端
4.2 基本语法
将.html改为.jsp后,顶部添加
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
jsp本质上就是.html,不过可以插入脚本语句,这里在网页上打印时间:
<% out.println(new java.util.Date().toLocalString()); %>
jsp内置了9个隐式对象(如request,session等) ,还可以利用java基础语法实现你想要的java后台操作。
4.3 EL表达式
格式:${表达式}
对比获取用户名和密码的操作:
<body>
用户名:<%=request.getAttribute("username")%><br />
密 码:<%=request.getAttribute("password")%><br />
<hr>
使用EL表达式:<br />
用户名:${username}<br />
密 码:${password}<br />
</body>
当然,它也有自己的规范,比如表达式不能数字开头,不能是保留字,不能是隐式对象,不能含 ' " - / 等特殊符号。
它还可以直接获取变量值 "http://localhost:8080/chapter/index.jsp?id=1",${id}就可访问id的值。
EL有11个内置对象,比如获取cookie的值的方法:
后台设置cookie;
Cookie cookie = new Cookie("username", "Username in cookie");
response.addCookie(cookie);
创建一个名称为username,值为"Username in cookie"的Cookie对象,然后发送给客户端。
然后我们就可以使用${cookie.username}获得这个cookie了,${cookie.username.name}获得cookie名称,${cookie.username.value}获得cookie值。
4.4 JSTL使用Core标签库
导入jar,在jsp<html>上加上
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:choose>类似与if-else ,<c:when>表示if, <c:otherwise>表示else
<c:choose>
<c:when test="${empty param.username}">
unKnown user.
</c:when>
<c:when test="${param.username=='itcast'}">
${ param.username} is manager.
</c:when>
<c:otherwise>
${ param.username} is employee.
</c:otherwise>
</c:choose>
<c:forEach>类似与foreach循环
<%
String[] fruits = { "apple", "orange", "grape", "banana" };
%>
String数组中的元素:
<c:forEach var="name" items="<%=fruits%>">
${name}<br />
</c:forEach>
5 乱码通杀
产生乱码的原因很多,不做讲解,这里指出解决方案
1. 首先统一编码,jsp与servlet编码设为utf-8
2. 然后servlet无脑上这三行代码:
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
3. 看这里:
https://blog.csdn.net/qq_38815856/article/details/80998774
之后就不用执行filename = new String(filename.trim().getBytes("iso8859-1"),"UTF-8")这种操作了。
6 filter拦截器
6.1 初步使用
它可以在拦截后修改request和response,这样实现很多开发者想得到的功能。比如统一编码,实现自动登陆等,但这里不做过多讲解。
新建一个servlet,写上
response.getWriter().write("Hello MyServlet ");
新建一个filter,看到
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
在里面写上
PrintWriter out=response.getWriter();
out.write("Hello MyFilter");
对 filter进行web.xml配置,详见第一章。
<filter>
<display-name>filter</display-name>
<filter-name>filter</filter-name>
<filter-class>it.cast.filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/servlet</url-pattern>
</filter-mapping>
用于拦截servlet,执行程序,只显示出:
Hello MyFilter
说明拦截成功。
6.2 filter链
可定义多个filter对同一个servlet拦截。
新建一个MyFilter01,同6.1写上
PrintWriter out=response.getWriter();
out.write("Hello MyFilter01<br />");
chain.doFilter(request, response);
新建一个MyFilter02,同6.1写上
PrintWriter out=response.getWriter();
out.write("MyFilter02 Before<br />");
chain.doFilter(request, response);
out.write("<br />MyFilter02 After<br />");
设置web.xml配置为
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>cn.itcast.chapter08.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
<filter-name>MyFilter02</filter-name>
<filter-class>cn.itcast.chapter08.filter.MyFilter02</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<servlet>
<description></description>
<display-name>MyServlet</display-name>
<servlet-name>MyServlet</servlet-name>
<servlet-class>cn.itcast.chapter08.filter.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
执行程序,结果为
Hello MyFilter01
MyFilter02 Before
Hello MyServlet
MyFilter02 After
其中chain.doFilter(request, response);作用是对servlet进行放行。所以Hello MyServlet在MyFilter02 After前面。
7 JDBC
在此学会后可以自己写一些简单的项目了,比如:
稍微复杂点的:
包含本博客的需要的全部jar包,项目白送。
这里演示遍历操作:
servlet写上
List<Javabean_name_pass> list=Jdbc.jdbc_select();
request.setAttribute("stu", list);
RequestDispatcher dis=request.getRequestDispatcher("traverse.jsp");
dis.forward(request, response);
return;
数据库的操作
//封装数据库连接
static PreparedStatement Jdbc_connection(String sql) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/dl","root", "123");
return conn.prepareStatement(sql);
}
//插入数据
static void jdbc_insert(String name,String pass) throws Exception{
String sql="insert into table_regist values(?,?)";
PreparedStatement stmt=Jdbc_connection(sql);
stmt.setString(1,name);
stmt.setString(2,pass);
stmt.executeUpdate();
}
//将数据库的数据存入集合,一般用于遍历数据库
static ArrayList<Javabean_name_pass> jdbc_select() throws Exception{
String sql="select * from table_regist ";//where id=?
PreparedStatement stmt=Jdbc_connection(sql);
ResultSet r=stmt.executeQuery(sql);
Javabean_name_pass str=null;
while (r.next()) {
String name=r.getString(1);
String pass=r.getString(2);
str=new Javabean_name_pass(name, pass);
lister.add(str);
}
return lister;
}
//查询并比较name,用于查重
static boolean jdbc_select_name(String name) throws Exception{
boolean flag=true;
String sql="select name from table_regist";
PreparedStatement stmt=Jdbc_connection(sql);
ResultSet r=stmt.executeQuery(sql);
while(r.next()){
if(name.equals(r.getString("name"))) {
flag=false;
break;
}
else {
flag=true;
}
}
return flag;
}
//删除数据
static void jdbc_delete(String name) throws Exception{
String sql="delete from table_regist where name=?";
PreparedStatement stmt=Jdbc_connection(sql);
stmt.setString(1, name);
stmt.executeUpdate();
}
最后traverse.jsp页面上写:
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td>名字</td>
<td>密码</td>
</tr>
<c:forEach items="${stu}" var="s">
<tr>
<td>${s.name}</td>
<td>${s.pass}</td>
<td><a href="http://localhost:8080/DL_servlet_regist/Jdbc_Delete?name=${s.name}">删除</a></td>
</tr>
</c:forEach>
</table>
8 下载和上传
8.1 上传
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
然后嘛,都是jar封装好的操作,代码有注释,直接上书上的实例:
jsp页面
<body>
<form action="UploadServlet" method="post"
enctype="multipart/form-data">
<table width="600px">
<tr>
<td>上传者</td>
<td><input type="text" name="name" /></td>
</tr>
<tr>
<td>上传文件</td>
<td><input type="file" name="myfile" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="上传" /></td>
</tr>
</table>
</form>
</body>
servlet页面
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
//设置ContentType字段值
response.setContentType("text/html;charset=utf-8");
// 创建DiskFileItemFactory工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置文件缓存目录,如果该目录不存在则新创建一个
File f = new File("D:\\TempFolder");
if (!f.exists()) {
f.mkdirs();
}
// 设置文件的缓存路径
factory.setRepository(f);
// 创建 ServletFileUpload对象
ServletFileUpload fileupload = new ServletFileUpload(factory);
//设置字符编码
fileupload.setHeaderEncoding("utf-8");
// 解析 request,得到上传文件的FileItem对象
List<FileItem> fileitems = fileupload.parseRequest(request);
//获取字符流
PrintWriter writer = response.getWriter();
// 遍历集合
for (FileItem fileitem : fileitems) {
// 判断是否为普通字段
if (fileitem.isFormField()) {
// 获得字段名和字段值
String name = fileitem.getFieldName();
if(name.equals("name")){
//如果文件不为空,将其保存在value中
if(!fileitem.getString().equals("")){
String value = fileitem.getString("utf-8");
writer.print("上传者:" + value + "<br>");
}
}
} else {
// 获取上传的文件名
String filename = fileitem.getName();
//处理上传文件
if(filename != null && !filename.equals("")){
writer.print("上传的文件名称是:" + filename + "<br>");
// 截取出文件名
filename = filename.substring(filename.lastIndexOf("\\") + 1);
// 文件名需要唯一
filename = UUID.randomUUID().toString() + "_" + filename;
// 在服务器创建同名文件
String webPath = "/upload/";
//将服务器中文件夹路径与文件名组合成完整的服务器端路径
String filepath = getServletContext().getRealPath(webPath + filename);
// 创建文件
File file = new File(filepath);
file.getParentFile().mkdirs();
file.createNewFile();
// 获得上传文件流
InputStream in = fileitem.getInputStream();
// 使用FileOutputStream打开服务器端的上传文件
FileOutputStream out = new FileOutputStream(file);
// 流的对拷
byte[] buffer = new byte[1024];//每次读取1个字节
int len;
//开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中
while ((len = in.read(buffer)) > 0)
out.write(buffer, 0, len);
// 关闭流
in.close();
out.close();
// 删除临时文件
fileitem.delete();
writer.print("上传文件成功!<br>");
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
8.2 下载
不需要jar包了,比上传简单。
jsp页面
<body>
<!-- <a href="/Chapter12Download/DownloadServlet?filename=1.jpg">文件下载 </a> -->
<a href="/Chapter12Download/DownloadServlet?filename=<%=URLEncoder.encode("风景.jpg", "utf-8")%>">文件下载 </a>
</body>
servlet页面
public void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
//设置ContentType字段值
response.setContentType("text/html;charset=utf-8");
//设置相应消息编码
response.setCharacterEncoding("utf-8");
//设置请求消息编码
request.setCharacterEncoding("utf-8");
//获取所要下载的文件名称
String filename = request.getParameter("filename");
//下载文件所在目录
String folder = "/download/";
// 通知浏览器以下载的方式打开
response.addHeader("Content-Type", "application/octet-stream");
response.addHeader("Content-Disposition",
"attachment;filename="+URLEncoder.encode(filename,"utf-8"));
// 通过文件流读取文件
InputStream in = getServletContext().getResourceAsStream(
folder+filename);
// 获取response对象的输出流
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len;
//循环取出流中的数据
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
doGet(request, response);
}
基本完工,如果有什么疑问或是博客内容有什么问题欢迎留言指正。