目前在学习J2EE的一些知识,因为老是听别人说SSH框架如何如何的好,但是自己又不知道这到底是怎么一回事,所以就打算从头把Web的一些知识好好的学习学习,就在学习的过程中,整理了一些相对比较容易忘记和重要的知识点。
response.setContentType("txt/html;charset=UTF-8");
response.getWriter().write("你好");
response.getOutputStream().write("你好".getBytes());
3:获取资源文件的方法(这里以在src下面的properties资源为例子,方法的优点缺点都写了)
* 1:ServletContext (任意文件,任意位置的,但是要在web环境下)
* 2:ResourceBundle (这种只能获取后缀为properties 的资源)
* 3:类加载器 (任意文件,任意位置的)
public void test11(){
//第一种方法
// ServletContext servletContext = this.getServletContext();
// //得到资源路径
// String path = servletContext.getRealPath("/WEB-INF/classes/hnu/scw/properce/p1.properties");
// Properties properties = new Properties();
// try {
// //加载资源
// properties.load(new FileReader(path));
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// String name = properties.getProperty("name");
// System.out.println(name);
//第二种方法
// ResourceBundle rbBundle = ResourceBundle.getBundle("hnu.scw.properce.p1");
// String name = rbBundle.getString("name");
// System.out.println(name);
//第三种方法
/*
* 拿到类加载器有三种方法
* 1:类名 如:ServletDemon1.class.getClassLoader()
* 2:对象名 如:this.getClass().getClassLoader() 这种最简单
* 3:Class.forName() 如:Class.forName("ServletDemon1").getClassLoader()
*/
// InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("hnu/scw/properce/p1.properties");
// Properties pp = new Properties();
// try {
// pp.load(inputStream);
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// String name = pp.getProperty("name");
// System.out.println(name);
/*
* 生成验证码
*/
private void getYanZhengMa(HttpServletResponse response) {
//设置一下颜色数组,为了验证码更加难辨认
Color[] yanse = {Color.RED ,Color.BLACK ,Color.GREEN , Color.BLUE};
//初始化验证码的宽和高
int width = 100 ;
int height = 60;
//初始化图片缓冲器
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) ;
//初始化画笔
Graphics gp = bi.getGraphics(); //这里是用图片来进行初始化,否则不知道是画在哪里
//设置画笔颜色
gp.setColor(Color.RED);
//画一个矩形的外框
gp.drawRect(0, 0, width, height);
//设置矩形填充的颜色
gp.setColor(Color.YELLOW);
//填充背景(下面是从1,1开始填充,如果从0,0开始,那么外框也会被修改了,后面-2也是同理)
gp.fillRect(1, 1, width-2, height-2);
//生成要填充的内容
Random random = new Random();
//设置验证码的干扰线(这是为了效果来进行开发的,可以没有)
gp.setColor(Color.BLUE);
//画30条干扰线
for(int i=0 ; i<30 ;i++){
gp.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
//下面的是画点
//gp.drawOval(random.nextInt(width), random.nextInt(height), 2, 2);
}
//设置填充的内容的颜色
gp.setColor(Color.RED);
//设置填充内容的大小
gp.setFont(new Font("幼圆", Font.BOLD + Font.ITALIC, 20));
//如果填充的内容要为中文的时候,需要这样处理
String content ="全国我觉得嘎斯的获奖情况大手笔的吧区隔化akshldeqw";
//要把上面的转为unicode编码,因为如果浏览器不支持中文的话就会出现乱码,如果在国内的话则没有什么影响
//用在线工具转也可以,但最好用代码来进行转变,因为以后开发肯定是动态的一种方式最好
//content ="\u5168\u56fd\u6211\u89c9\u5f97\u560e\u65af\u7684\u83b7\u5956\u60c5\u51b5\u5927\u624b\u7b14\u7684\u5427\u533a\u9694\u5316\u0061\u006b\u0073\u0068\u006c\u0064\u0065\u0071\u0077";
for(int i =0 ; i < 4 ;i++){
//gp.setColor(yanse[random.nextInt(3)]);设置填充的颜色随即化(为了验证码更复杂)
char c =content.charAt(random.nextInt(content.length()));
gp.drawString(c + "", 20 + 20*i, 30); //开始填充内容和位置
}
//如果想要验证码是数字的,则填充的内容为数字(生成四个数字)
// for(int i=0 ; i<4 ;i++){
// int number = random.nextInt(10); //生成10以内的数字
// gp.drawString(number + "", 20 + 20*i, 30); //开始填充内容和位置
// }
//设置不要缓存
response.setHeader("Expires", -1+"");
response.setHeader("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache");
//将验证码显示到对应的位置
try {
ImageIO.write(bi, "jpg", response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
(1)当以Post方式进行提交时,只需要设置为
request.setCharacterEncoding("UTF-8");
(2)当以Get方式进行提交时,则需要重建获取到的内容,比如表单提交了一个name过来,则
String name =request.getParameter("name");
name = new String(name.getBytes("ISO-8859"),"UTF-8");
当然,想想,如果填写中文的控件比较多,那么上面的方法就很麻烦了,所以就需要换一种方法。
这时候就需要更改一下服务器的内容配置了,就在端口号配置的Connector的地方,加上URIEncoding = “UTF-8”,这样就可以了。这主要就是
就是改变服务器编码的方式来达到效果。
(3)当直接在地址栏中输入中文传送过来时,则需要如下进行处理了。
比如地址为:http://localhost:8080/MyServletDemo/servlet/ChineseDemo1?username="我爱中国";
这样的就需要如下处理:(注意这时候不需要更改服务器中的配置的encoding编码方式,对比一下情况(2))
String name =request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"));
response.setStatus(302);
response.setHeader("location", request.getContexPath()+"/ServletDemo1");
(2)使用response 对象中的sendRedirect()方法实现重定向
response.sendRedirect(request.getContexPath()+"/ServletDemo1");
8:请求转发的方法
RequestDispatcher rd = request.getRequestDispatcher("/ServletDemo1");
rd.forward(request, response);
请求重定向和请求转发的区别:
RequestDispatcher rd = request.getRequestDispatcher("/ServletDemo1");
rd.include(request, response);
请求包含和请求转发的区别:
String userage = request.getAttribute("age");
response.setHeader("Refresh","2");
(2)刷新到其他页面
response.setHeader("Refresh","2;url=""/工程名+要刷新去的页面地址");
response.setDateHeader("Expiress",System.currentTimeMllis()+1000);
Cookie c = new Cookie("要删除的Cookie的名字"," ");
c.setMaxAge(0);
response.addCookie(c);
(1):访问Servlet(从Servlet中返回数据)比如:
(2):访问WebContent的图片,比如
(3)访问Src目录下的图片,比如
其中的path是在Servlet中获取;如String path = this.getServletContext().getRealPath("/WEB-INF/classes/qwer.png"); //下载gif或者图片
(方法一:在doPost方法中或者doGet方法中)
OutputStream out = response.getOutputStream();
//读取本地图片输入流
FileInputStream inputStream = new FileInputStream(path);
int i = inputStream.available();
//byte数组用于存放图片字节数据
byte[] buff = new byte[i];
inputStream.read(buff);
//记得关闭输入流
inputStream.close();
//设置发送到客户端的响应内容类型
response.setContentType("image/*");
out.write(buff);
//关闭响应输出流
out.close();
(方法二:)
public class ImageShowServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream os = response.getOutputStream();
File file = new File("C:\\abc.jpg");
FileInputStream fips = new FileInputStream(file);
byte[] btImg = readStream(fips);
os.write(btImg);
os.flush();
}
/**
* 读取管道中的流数据
*/
public byte[] readStream(InputStream inStream) {
ByteArrayOutputStream bops = new ByteArrayOutputStream();
int data = -1;
try {
while((data = inStream.read()) != -1){
bops.write(data);
}
return bops.toByteArray();
}catch(Exception e){
return null;
}
}
}
方法一:System,nanoTime() 方法
Random rd = new Random();
String flag = System.nanoTime()+""+ rd.nextInt() ; //理论上可能产生重复的,但实际不会
String flag = UUID.randomUUID().toString();
方法三:采用数据指纹的方式
String flag = UUID.randomUUID().toString();
//先进行MD5加密(还有SAH加密)
MessageDigest md = MessageDigest.getInstance("md5");
byte[] bs = flag.getBytes();
//采用数据指纹进一步加密
BASE64Encoder base = new BASE64Encoder();
String mima = base.encode(bs); //得到最终的密文
解释一下上面的知识:其中的MD5加密就是一种加密算法,保密程度相对很高。所以这一步就很难破解了,另外讲一下关于BASE64Encoder这个类,其实这个类并不是JDK中自带的,而是Sun公司自己开发出来的,所以不能直接的引用到这个类,需要进行特殊处理,其中的步骤如下:
1:右击项目工程,点击Properties,
2:弹出一个框,然后点击Java Build Path,然后点击Libraries,点击Apache Tomacat (也就是默认的第一个)
3:这时候会看到Access rules这个,默认是显示着No rules defind,这时候点击一下,就显示Edit,进行添加规则。
4:又会弹出一个框,然后点击add,继续一个框,
5:在新的框中,第一个选项选择Accessible,第二个地方填入**(切记是这个符号,关于其他的可以参考那下面提示的一些其他的内容)
6:通过上面的方法,然后就可以引用了,记得是通过ctrl+shift+o(这是我默认的快捷键),注意不是ctrl+shift+f,这个普通的引用快捷,它们是有区别的
好了,再解释下关于BASE64Encoder这个类的具体方法,它其实做的就是将三字节扩充为四字节,,,,这样是不是破解难度又增加了呢?哈哈······
关键点:就是在客户端提交的时候,产生一个唯一的Token(这个在上面的一个问题中进行了方法的讲解),放入到Session中进行保存,并且在form表单中用一个进行存储这个token值,然后再提交后的界面进行读取。首先读取传送过来的参数的值,并且与session中的进行比较,如果相同,则表示是首次提交,这时候关键点,记住,当确认是首次提交后,需要将这个session里面的值进行删除。因为这样即使重新刷新当前页面,那么session里面就是空了,不会存在相等的情况,就表示不是首次提交,这样就能达到防止重复提交的功能。