学习J2EE路途中一些有用的知识点(一)真正的干货

      目前在学习J2EE的一些知识,因为老是听别人说SSH框架如何如何的好,但是自己又不知道这到底是怎么一回事,所以就打算从头把Web的一些知识好好的学习学习,就在学习的过程中,整理了一些相对比较容易忘记和重要的知识点。

      1:输出中文内容防止乱码(有五种方法,但是下面记录最简单的吧)

response.setContentType("txt/html;charset=UTF-8");

       2:字符输出流和字节输出流不能同时存在。 比如:

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);

         4: request对象的一些方法

学习J2EE路途中一些有用的知识点(一)真正的干货_第1张图片

5:随机验证码的生成(主要是对画笔类的掌握)

/*
	 * 生成验证码
	 */
	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();
		}
	}

 6:解决request提交的中文乱码问题

(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"));

 7:请求重定向的方法

           (1):使用 http头信息
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);
         请求重定向和请求转发的区别:
         重定向的时候地址栏会变化,而转发的时候地址栏是不会变化的.(请求重定向:两个请求;;;请求转发:一个请求)

9:请求包含的方法

RequestDispatcher rd = request.getRequestDispatcher("/ServletDemo1");
rd.include(request, response);
请求包含和请求转发的区别:
作用其实差不多一样,但是在包含的意思就是相当于把转发的Servlet中的内容可以获取到,在前面的Servlet可以得到(转发也可以),但是他们的方向存在一定的差别
比如:在ServletDemo进行请求包含到ServletDemo2
在ServletDemo2中有,request.setAttribut("age","100");
这样的话,在ServletDemo1中就可以直接提前拿到了。
String userage = request.getAttribute("age");

        10:request对象的请求转发和ServletContext对象的请求转发的区别:

               request对象的支持相对路径,而ServletContext对象的不支持相对路径的写法。
  11:URL的写法(也就是到底什么时候需要加工程路径,什么时候不需要)
          (1)客户端都要写工程名称(request.getContextPath())
           比如:表单,超链,标签,img,link,script,请求重定向
(2)服务器端不需要加工程名
  比如:请求转发,请求包含

12:页面刷新

         (1)刷新当前页面(2秒后刷新)  
response.setHeader("Refresh","2");
(2)刷新到其他页面  
response.setHeader("Refresh","2;url=""/工程名+要刷新去的页面地址");

13:控制缓存的时间(这里时用10秒)

response.setDateHeader("Expiress",System.currentTimeMllis()+1000);

14:如何删除Cookie(官方是没有删除Cookie的这个API),所以就需要重新创建一个同名的,并设置存活时间为0,则可以

        Cookie c = new Cookie("要删除的Cookie的名字"," ");

        c.setMaxAge(0);

response.addCookie(c);

15:关于Img标签的src属性问题

      (1):访问Servlet(从Servlet中返回数据)比如:

未知

     (2):访问WebContent的图片,比如

未知

     (3)访问Src目录下的图片,比如

  其中的path是在Servlet中获取;如String path = this.getServletContext().getRealPath("/WEB-INF/classes/qwer.png"); //下载gif或者图片

图片缓存失败

16:HTML页面读取从Servlet中获取本地图片进行显示

(方法一:在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;  
        }  
    }  
}  

17:创建唯一的值(用在Token 的生成中)

方法一:System,nanoTime() 方法

     Random rd = new Random();
String flag = System.nanoTime()+""+ rd.nextInt() ;     //理论上可能产生重复的,但实际不会

方法二:采用UUID类(采用128位的方式)

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这个类的具体方法,它其实做的就是将三字节扩充为四字节,,,,这样是不是破解难度又增加了呢?哈哈······

18:防止客户端重复提交数据(这个用在客户端进行注册的时候都能用到这个技术处理)

关键点:就是在客户端提交的时候,产生一个唯一的Token(这个在上面的一个问题中进行了方法的讲解),放入到Session中进行保存,并且在form表单中用一个进行存储这个token值,然后再提交后的界面进行读取。首先读取传送过来的参数的值,并且与session中的进行比较,如果相同,则表示是首次提交,这时候关键点,记住,当确认是首次提交后,需要将这个session里面的值进行删除。因为这样即使重新刷新当前页面,那么session里面就是空了,不会存在相等的情况,就表示不是首次提交,这样就能达到防止重复提交的功能。

19:Session默认的存活时间30分钟,这个可以在配置文件web.xml中进行修改的。比如:

15

你可能感兴趣的:(JavaWeb,java,J2EE,基本知识,易错点,关键知识)