JavaWeb学习笔记整理3
1、通过反射优化方法调用
Servlet是JavaWeb极其重要的一部分,客户端可通过Servlet调用各种方法来实现功能,在前台实现功能时,后台通过得到相应的方法名来决定执行什么方法,如果这时候用if-else来判断就会导致效率低下,同时若方法过多也会导致代码行繁多;故可用类加载器反射得到方法来调用,具体代码如下:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决post请求中文乱码问题
request.setCharacterEncoding("UTF-8");
//解决响应中文乱码问题
response.setContentType("text/html; charset=UTF-8");
String action = request.getParameter("action");
//反射优化大量elseif代码
try {
//获取action业务鉴别字符串,获取相应的业务、方法反射对象
Method method =
this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
//调用目标业务方法
method.invoke(this,request,response);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e); //把异常抛给Filter过滤器
}
}
//获取action业务鉴别字符串,获取相应的业务、方法反射对象
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
//调用目标业务方法
method.invoke(this,request,response);
this.getClass()是获取当前对象的类加载器,
getDeclaredMethod(String name, Class<?>... parameterTypes),第一个参数为方法名,后面参数为方法的参数的类。
2、request和response
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
当需要获取客户机端提交过来的数据时,找request对象;当需要向客户机输出数据,找response对象。
请求响应的具体现实流程:
- 1.浏览器发送请求
- 2.服务器接收请求,创建两个对象(request和response),将请求的信息封装request对象
- 3.找到对应的servlet,将这两个对象传递给servlet
- 4.Servlet收到请求,执行service方法,处理自己的业务逻辑,生成动态的内容,将内容返回给服务器
- 5.服务器收到内容之后,进行拆分,生成响应信息,返回给浏览器
request简述
request获取参数值:request.getParameter(String s);
该参数有多个值时要用: request.getParameterValues(String s);
获取全部参数:request.getParameterMap()。
其余API:
- getRequestURI() 获取请求的资源路径
- getRequestURL() 获取请求的统一资源定位符(绝对路径)
- getRemoteHost() 获取客户端的IP地址
- getHeader() 请求头
- getMethod() 请求的方式
request对象也是一个存储数据的区域对象,所以也具有如下方法:
- setAttribute(String name, Object o)
- getAttribute(String name)
- removeAttribute(String name)
response简述
设置状态码
setStatus(int sc)
- 200 正确
- 302 重定向
- 304 查找本地缓存
- 404 请求资源不存在
- 500 服务器内部错误
设置响应头:setHeader(String name,String value)
setContentType 会同时设置服务器和客户端都使用UTF-8字符集,也设置了响头
该方法一定要在获取流对象之前调用才有效
response.setContentType("text/html;UTF-8");
响应流
响应流有以下两个
字符流
PrintWriter writer = response.getWriter();
writer.println("w分段函数覅u和ponse");
字节流
response.getOutputStream();
文件的上传与下载
上传UploadServlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//先判断上传的数据是否为多段数据(只有是多段的数据,才是文件上传的)
if (ServletFileUpload.isMultipartContent(request)) {
//创建FileItemFactory工厂实现类
DiskFileItemFactory itemFactory = new DiskFileItemFactory();
//创建用于解析上传数据的工具类ServletFileUpload类
ServletFileUpload servletFileUpload = new ServletFileUpload(itemFactory);
try {
List<FileItem> list = servletFileUpload.parseRequest(request);
//循环判断每一个表单项,是普通类型,还是上传的文件
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
//普通表单项
System.out.println("表单项的name属性值:" + fileItem.getFieldName());
System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));
} else {
//上传的文件
System.out.println("表单项的name属性值:" + fileItem.getFieldName());
System.out.println("上传的文件名:" + fileItem.getName());
//上传的文件下载到本地
fileItem.write(new File("e:\\" + fileItem.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
下载DownServlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取下载的文件名
String downloadFileName = "2.jpg";
//2、读取要下载的文件内容(通过ServletContext对象可以读取)
ServletContext servletContext = getServletContext();
//获取要下载的文件类型
String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
System.out.println("下载的文件类型:" + mimeType);
//回传前,通过响应头告诉客户端返回的数据类型
response.setContentType(mimeType);
//告诉客户端收到的数据是用于下载使用(用响应头)
//Content-Disposition响应头,表示收到的数据怎么处理
//attachment表示附件,表示下载使用
//filename= 表示指定下载的文件名,可以用别的名字 如"attachment;filename=22.jpg"
//用中文文件名的话要对文件名重新编码URLEncoder.encode("照片.jpg","UTF-8")
response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("截图1.jpg","UTF-8"));
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
//获取响应的输出流
ServletOutputStream outputStream = response.getOutputStream();
//3、把下载的文件回传给客户端
//读取输入流中所有的数据,复制给输出流,输出给客户端
IOUtils.copy(resourceAsStream,outputStream);
}
请求转发与请求重定向
请求转发:request.getRequestDispatcher(URL地址).forward(request, response)
处理流程:
- 客户端发送请求,Servlet做出业务逻辑处理。
- Servlet调用forword()方法,服务器Servlet把目标资源返回给客户端浏览器。
请求重定向:response.sendRedirect(URL地址)
处理流程:
- 客户端发送请求,Servlet做出业务逻辑处理。
- Servlet调用response.sendReadirect()方法,把要访问的目标资源作为response响应头信息发给客户端浏览器。
- 客户端浏览器重新访问服务器资源xxx.jsp,服务器再次对客户端浏览器做出响应。
请求转发特点:
1、浏览器地址栏不会发生变化
2、只有一次请求
3、共享Request域中的数据
4、不可以访问工程外的资源
重定向特点:
1、浏览器地址栏会发生变化
2、共有两次请求
3、不能共享Request中的数据
4、可以访问工程外的资源
- request.getRequestDispatcher()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;服务器内部转发,整个过程处于同一个请求当中。
- response.sendRedirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。不在同一个请求。重定向,实际上客户端会向服务器端发送两个请求。
- 所以转发中数据的存取可以用request作用域:
request.setAttribute(), request.getAttribute()
,重定向是取不到request中的数据的。只能用session。 - forward()更加高效,在可以满足需要时,尽量使用RequestDispatcher.forward()方法。(思考一下为什么?)
- RequestDispatcher是通过调用HttpServletRequest对象的getRequestDispatcher()方法得到的,是属于请求对象的方法。
- sendRedirect()是HttpServletResponse对象的方法,即响应对象的方法,既然调用了响应对象的方法,那就表明整个请求过程已经结束了,服务器开始向客户端返回执行的结果。
- 重定向可以跨域访问,而转发是在web服务器内部进行的,不能跨域访问。
转发与重定向中路径的区别:
灵活获取工程地址:
String basepath = req.getScheme() //协议 http
+ "://"
+ req.getServerName() //localhost或127.0.0.1或者其他,根据访问地址灵活获取
+ ":"
+ req.getServerPort() //8080
+ req.getContextPath() // /ser1 工程名
+ "/";
四大作用域