使用Map封装请求信息并显示

本文详细介绍了一个基于Java的Web应用中如何实现文件上传功能,包括表单设计、异常处理、自定义对象封装、文件类型验证及存储路径设定。通过具体代码示例,展示了如何使用Servlet、FileItem和自定义工具类进行文件上传与数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Map封装请求信息并显示

在这里插入图片描述
upload.jsp表单文件:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h3>文件上传</h3><br/>
	<span style="color:red;">${errorMsg}</span>
	<form action="/upload-download-i18n/upload" method="POST" enctype="multipart/form-data">
		账号:<input type="text" name="username"/><br/>
		邮箱:<input type="text" name="email"/><br/>
		头像:<input type="file" name="headImg" accept="image/*"/><br/>
		<input type="submit" value="朕要提交"/><br/>
	</form>
</body>
</html>

自定义异常类(LogicException):

public class LogicException extends RuntimeException{
	private static final long serialVersionUID = 1L;

	public LogicException(String message, Throwable cause) {
		super(message, cause);
	}

	public LogicException(String message) {
		super(message);
	}
	
}

一、新建一个对象类(如:user)

@Data
public class User {
	private String username = null;
	private String email = null;
	private String imageUrl = null;//图片保存的路径  (JSP:<img src="${user.imageUrl}">)
	private String imageName = null;//图片的原始名称
}

二、在调用者类(UplocalServlet.java)中获得upload.jsp传入的参数值,并赋值给user对象,再在user.jsp中显示;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			User user = new User();
			//-------------------往user对象中传入数据-------------------------
			//封装普通表单的数据
			//key:参数名称
			//value:参数值
			Map<String,String> fieldMap = new HashMap<>();
			//封装上传图片(因为要通过一个key获得两个value,所以对图片进行再封装)
			//key:参数名称
			//value:ImgFile对象同时封装了imgeUrl和imageName
			Map<String,ImgFile> imgMap = new HashMap<>();
			
			FileUtil.upload(req,fieldMap,imgMap);
			
			user.setUsername(fieldMap.get("username"));
			user.setEmail(fieldMap.get("email"));
			
			user.setImageName(imgMap.get("headImg").getImageName());
			user.setImageUrl(imgMap.get("headImg").getImageUrl());
			
			//---------------------------------------------------------------
			System.out.println(user);
			System.out.println(fieldMap);
			System.out.println(imgMap);
			req.setAttribute("user", user);
			req.getRequestDispatcher("/user.jsp").forward(req, resp);
		}catch(LogicException e) {
			String errorMsg = e.getMessage();//获取异常信息
			req.setAttribute("errorMsg",errorMsg);
			req.getRequestDispatcher("/upload.jsp").forward(req, resp);
		}
	}
}

三、封装的ImgFile类(保存图片相对路径和真实名称)

@Data
public class ImgFile {
	private String imageUrl = null;//图片保存的路径  (JSP:<img src="${user.imageUrl}">)
	private String imageName = null;//图片的原始名称
}

四、使用自定义的工具类(FileUtil.java)进行接受处理upload.jsp传入的参数

public class FileUtil {
	
	//允许接受上传的文件类型(如:图片)
	private static final String ALLOWED_IMAGE_TYPE="png;gif;jpg;jpeg";

	public static void upload(HttpServletRequest req,Map<String,String> fieldMap,Map<String,ImgFile> imgMap){
		//解析和检查请求:请求方式是否是POST,请求编码是否是muitipart/form-data
		boolean isMultipart = ServletFileUpload.isMultipartContent(req);
		if(!isMultipart) {
			return;
		}
		try {
			//1.创建FileItemFactory对象
			//FileItemFactory是用来创建FileItem对象的
			//FileItem对象:form表单中的表单控件的封装
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//2.创建文件上传处理器
			ServletFileUpload upload = new ServletFileUpload(factory);
			
				//设置单个上传文件的大小限制
				upload.setFileSizeMax(1024*1024*2);//2M
				//设置该次请求总数据大小限制
				upload.setSizeMax(1024*1024*3);//3M
			
			//3.解析请求
			List<FileItem> items = upload.parseRequest(req);
			//4.迭代出每一个FileItem
			for(FileItem item : items) {
				String fieldName = item.getFieldName();//获取表单控件的name属性值(参数名)
				if(item.isFormField()) {
				//普通表单控件
					//得到控件的参数值
					String value = item.getString("UTF-8");
					//存储控件名称(jsp文件中的name)和对应的value值,最后返回到调用者中进行读取
					fieldMap.put(fieldName,value);
				}else {
					//-----------------------判断上传文件格式是否符合要求------------
					//上传文件的拓展名
					String ext = FilenameUtils.getExtension(item.getName());
					String[] allowedImageType = ALLOWED_IMAGE_TYPE.split(";");
					
					//当前上传类型不再允许的范围内
					if(!Arrays.asList(allowedImageType).contains(ext)) {
						throw new LogicException("上传格式错误,请重新上传");
						
					}
					//----------------------------------------------------------
					//表单上传控件
					System.out.println("上传文件的名称:"+item.getName());
					//文件名称
					String fileName = UUID.randomUUID().toString()+"."
									+FilenameUtils.getExtension(item.getName());
					//目标的绝对路径"E:/JAVA/My_eclipseEE/upload-download-i18n/webapp/upload"
					String dir = req.getServletContext().getRealPath("/upload");
					//把二进制数据写到哪一个文件中
					item.write(new File(dir, fileName));	
					
					//-----------将图片中的真实名字和图片相对路径保存在imgMap中,最后返回给调用者-------------------------
					ImgFile img = new ImgFile();
					img.setImageUrl("/upload/"+fileName);
					img.setImageName(FilenameUtils.getName(item.getName()));
					imgMap.put(fieldName,img);
					//---------------------------------------------------
				}
			}
		}catch(FileSizeLimitExceededException e) {
			throw new LogicException("单个上传文件大小不能超过2M",e);//继续抛出异常类给该类调用者(UploadServlet)
		}catch(SizeLimitExceededException e) {
			throw new LogicException("该次请求大小不能超过3M",e);//继续抛出异常类给该类调用者(UploadServlet)
		}catch(LogicException e) {
			throw e;//继续抛出异常类给该类调用者(UploadServlet)
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

五、在user.jsp中显示表单输入的内容

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	${user}<br/>
	名称:${user.username}<br/>
	邮箱:${user.email}<br/>
	头像:${user.imageName}<br/>
	<img alt="" src="${user.imageUrl}"><br/>
</body>
</html>


upload.jsp:
在这里插入图片描述

user.jsp:
在这里插入图片描述

<think>我们参考用户的问题:“我想了解如何在ReactNative中封装使用请求功能请问ReactNative请求封装使用方法”根据引用内容,我们知道在ReactNative中可以使用XMLHttpRequest或者fetch进行网络请求且通常会对fetch进行封装以方便使用。目标:封装一个简单的网络请求工具,支持GET和POST请求展示使用方法。设计思路:1.创建一个名为`http.js`的文件,用于封装网络请求。2.封装GET和POST方法,使用fetchAPI。3.考虑请求头、请求体、错误处理等。4.在组件中使用封装好的请求方法。步骤:1.封装fetch请求:-设置基本的请求配置(如超时、请求头等)。-对请求参数进行处理。-统一处理响应和错误。2.创建两个函数:get和post。3.在组件中引入使用。具体实现:在`http.js`文件中:```javascriptconstBASE_URL='http://your-api-base-url';//替换为你的API基础地址/***封装get方法*@paramurl请求的URL,相对路径*@paramparams请求参数,对象形式*@returns{Promise<any>}*/exportconstget=(url,params={})=>{//将参数拼接到URL上letquery=Object.keys(params).map(k=>encodeURIComponent(k)+'='+encodeURIComponent(params[k])).join('&');if(query){url+=(url.includes('?')?'&':'?')+query;}returnfetch(BASE_URL+url,{method:'GET',headers:{'Content-Type':'application/json',//可以在这里添加全局headers,比如token//'token':'your-token',},}).then(response=>{if(!response.ok){thrownewError('网络请求失败');}returnresponse.json();}).catch(error=>{console.error('GET请求错误:',error);throwerror;});};/***封装post方法*@paramurl请求的URL,相对路径*@parambody请求体,对象形式*@returns{Promise<any>}*/exportconstpost=(url,body={})=>{returnfetch(BASE_URL+url,{method:'POST',headers:{'Content-Type':'application/json',//可以在这里添加全局headers,比如token//'token':'your-token',},body:JSON.stringify(body),}).then(response=>{if(!response.ok){thrownewError('网络请求失败');}returnresponse.json();}).catch(error=>{console.error('POST请求错误:',error);throwerror;});};```在组件中使用:```javascriptimportReact,{useEffect}from'react';import{View,Text}from'react-native';import{get,post}from'./http';//根据实际路径调整constApp=()=>{useEffect(()=>{//使用get请求get('/some-endpoint',{param1:'value1'}).then(data=>{console.log('GET请求成功:',data);}).catch(error=>{console.log('GET请求失败:',error);});//使用post请求post('/another-endpoint',{key:'value'}).then(data=>{console.log('POST请求成功:',data);}).catch(error=>{console.log('POST请求失败:',error);});},[]);return(<View><Text>网络请求示例</Text></View>);};exportdefaultApp;```说明:1.我们创建了一个`http.js`模块,导出了`get`和`post`两个方法。2.在组件中,我们通过导入这两个方法,在`useEffect`中发起请求。3.在GET请求中,我们将参数拼接在URL上;在POST请求中,我们将参数放在请求体中,设置为JSON格式。4.我们设置了基础的错误处理,如果请求失败(如网络错误或HTTP状态码非200-299),则会抛出错误。注意事项:-在实际项目中,可能需要更完善的封装,比如处理超时、添加拦截器、统一处理错误消息等。-请求头中的`token`等认证信息,通常需要从存储中读取(如AsyncStorage),这里为了简单直接注释掉了,实际使用时应动态获取。-如果API返回的HTTP状态码不在200-299范围内,`response.ok`为false,我们将其视为错误。这样封装后,可以在项目中任何需要网络请求的地方使用,避免了重复代码,也方便统一管理。§§相关问题§§1.如何为封装请求添加超时功能?2.如何处理网络请求中的认证(如token过期)?3.在ReactNative中如何安全地存储认证信息(如token)?</think>### React Native 请求封装使用方法 在 React Native 中进行网络请求时,推荐使用 **fetch API** 或 **axios** 库。为提高代码复用性和可维护性,建议对请求进行封装。以下是详细实现步骤: --- #### 一、基础封装方案 创建 `http.js` 文件封装请求方法: ```javascript // http.js const BASE_URL = 'https://your-api-domain.com/api'; const http = { get: async (endpoint, params = {}) => { try { // 拼接查询参数 const query = new URLSearchParams(params).toString(); const url = `${BASE_URL}${endpoint}?${query}`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN', // 认证头 }, }); if (!response.ok) throw new Error(`HTTP ${response.status}`); return response.json(); } catch (error) { console.error('GET请求失败:', error); throw error; } }, post: async (endpoint, data = {}) => { try { const response = await fetch(`${BASE_URL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN', }, body: JSON.stringify(data), }); if (!response.ok) throw new Error(`HTTP ${response.status}`); return response.json(); } catch (error) { console.error('POST请求失败:', error); throw error; } } }; export default http; ``` --- #### 二、在组件中使用 ```javascript // App.js import React, { useEffect } from 'react'; import http from './http'; const App = () => { // GET请求示例 const fetchData = async () => { try { const result = await http.get('/users', { page: 1, limit: 10 }); console.log('获取数据:', result); } catch (err) { console.log('请求出错:', err); } }; // POST请求示例 const submitData = async () => { try { const response = await http.post('/login', { username: 'admin', password: '123456' }); console.log('登录结果:', response); } catch (err) { console.log('提交失败:', err); } }; useEffect(() => { fetchData(); }, []); return (...); }; ``` --- #### 三、关键优化点 1. **统一错误处理** 在封装层添加全局错误拦截器: ```javascript // 在http.js中添加 const handleError = (error) => { if (error.message.includes('401')) { // token过期处理 navigateToLogin(); } return Promise.reject(error); }; // 在每个方法末尾添加: .catch(handleError) ``` 2. **超时控制** 使用 `AbortController` 实现请求超时: ```javascript const controller = new AbortController(); setTimeout(() => controller.abort(), 10000); // 10秒超时 fetch(url, { signal: controller.signal, // ...其他配置 }); ``` 3. **文件上传** 扩展 `upload` 方法: ```javascript upload: async (endpoint, file) => { const formData = new FormData(); formData.append('file', file); return fetch(`${BASE_URL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'multipart/form-data' }, body: formData }); } ``` --- #### 四、axios 替代方案 若需更强大功能(拦截器、取消请求等),推荐使用 axios: ```javascript // http-axios.js import axios from 'axios'; const instance = axios.create({ baseURL: 'https://your-api-domain.com/api', timeout: 10000, }); // 请求拦截器 instance.interceptors.request.use(config => { config.headers.Authorization = 'Bearer YOUR_TOKEN'; return config; }); // 响应拦截器 instance.interceptors.response.use( response => response.data, error => { if (error.response?.status === 401) { navigateToLogin(); } return Promise.reject(error); } ); export default instance; ``` --- ### 注意事项 1. **跨平台兼容性** React Native 的 `fetch` 实现与浏览器略有差异,需测试 Android/iOS 双平台[^1]。 2. **安全存储** 认证 token 应使用 `react-native-keychain` 等安全存储方案。 3. **调试工具** 使用 React Native Debugger 或 Flipper 监控网络请求。 > 封装核心原则:**统一入口、集中管理、错误隔离**。基础封装已满足多数场景,复杂项目建议采用 axios + TypeScript 增强类型安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值