京东笔试题总结

1.程序题,当输入type=4时,写出以下代码的输出: 

switch (type) {
        default:
            System.out.print(4);
        case 1:
            System.out.print(1);
        case 2:
            System.out.print(2);
        case 3:
            System.out.print(3);
        }
输出:4 3 2 1 说明,如果第一个匹配成功,则后面的都会执行,除非遇到break;type类型:

switch表达式后面的数据类型只能是byte,short,char,int四种整形类型,枚举类型和java.lang.String类型(从java 7才允许),不能是boolean类型。

在网上看到好多文章,说switch还支持byte,short,char,int 的包装类,首先可以肯定说switch不支持这些包装类,但是如下的代码又是正确的:

public static void main(String[] args) {
        switch (new Integer(45)) {
        case 40:
            System.out.println("40");
            break;
        case 45:
            System.out.println("45");//将会打印这句
            break;
        default:
            System.out.println("?");
            break;
        }
    }

可以打印正确的结果,在挨着挨着试完Byte,Short,Character,Integer后发现都可以正确打印,于是便说switch也支持byte,short,char,int的包装类。这种说法不完全正确,之所以switch能够支持他们的包装类,是因为自动拆箱(从JDK1.5开始支持自动拆箱和自动装箱,自动拆箱就是自动将引用数据类型转化为基本数据类型,自动装箱就是自动将基本数据类型转化为引用数据类型)的原因,下面使用jclasslib软件打开上面的.class文件,

0 new #2 <java/lang/Integer>                             创建一个Integer类的对象
3 dup                                                    将对象的标识压入栈顶部
4 bipush 45                                              将整形45压入栈中
6 invokespecial #3 <java/lang/Integer.<init>>            调用Integer类型的构造方法
9 invokervirtual #4 <java/lang/Integer.intValue>         调用intValue()方法
12 lookupswitch 2
        40:40(+28)
        45:51(+39)
        defalut:62(+50)
40 getstatic #5 <java/lang/System.out>                   获得标准输出流
43 ldc #6 <40>                                           从常量池中将40的索引压入栈中
45 invokevirtual #7 <java/io/PrintStream.println>        调用println()方法
48 goto 70 (+22)
51 gestatic #5 <java/lang/System.out>
54 ldc #8 <45>
56 invokevirtual #7 <java/io/PrintStream.println>
59 goto 70 (+11)
62 getstatic #5 <java/lang/System.out>
65 ldc #9<?>
67 invokevirtual #7 <java/io/PrintStream.println>
70 return

从上面的第5行我们可以看出编译器自动调用了intValue()方法,如果是使用Byte会自动调用byteValue()方法,如果是Short会自动调用shortValue()方法,如果是Integer会自动调用intValue()方法。switch 的查找原理是使用key-offset在目标表格中查找的,lookupswitch后面的数字和goto后面的数字都是有规律的,关于更多信息可以查看The Java® Virtual Machine Specification

因此switch表达式后面的数据类型只支持byte,short,char,int四种整形类型、枚举类型和java.lang.String类型。

转载:https://www.cnblogs.com/HDK2016/p/6854671.html
View Code

2.程序题,以下代码最后会抛出一个异常,是第几行抛出的:

try{
            throw new Exception("1");
        }catch (IOException e){
            throw new Exception("2");
        }catch (Exception e) {
            throw new Exception("3");
        }finally {
            throw new Exception("4");
        }

解析:  4    有待研究  抛出最后new的exception异常

try{
            throw new Exception("1");
        }catch (IOException e){
            throw new Exception("2");
        }catch (Exception e) {
            throw e;
//            throw new Exception("3");
        }
            finally {
            throw new Exception("4");
        }
java.lang.Exception: 4
try{
            throw new Exception("1");
        }catch (IOException e){
            throw new Exception("2");
        }catch (Exception e) {
//            throw e;
            throw new Exception("3");
        }
            finally {
//            throw new Exception("4");
        }
    }
java.lang.Exception: 3
try{
            throw new Exception("1");
        }catch (IOException e){
            throw new Exception("2");
        }catch (Exception e) {
            throw e;
//            throw new Exception("3");
        }
            finally {
//            throw new Exception("4");
        }
java.lang.Exception: 1

 3、web容器有几种作用域?如何防止SQL注入?

一、SQL注入简介

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。

二、SQL注入攻击的总体思路

1.寻找到SQL注入的位置

2.判断服务器类型和后台数据库类型

3.针对不通的服务器和数据库特点进行SQL注入攻击

三、SQL注入攻击实例

比如在一个登录界面,要求输入用户名和密码:

可以这样输入实现免帐号登录:

用户名: ‘or 1 = 1 –

密 码:

点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库API已经处理了这些问题)

这是为什么呢? 下面我们分析一下

从理论上说,后台认证程序中会有如下的SQL语句:

String sql = "select * from user_table where username=' "+userName+" ' and password=' "+password+" '";
当输入了上面的用户名和密码,上面的SQL语句变成:

SELECT * FROM user_table WHERE username='’or 1 = 1 -- and password='’
分析SQL语句:

条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;

然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

这还是比较温柔的,如果是执行

SELECT * FROM user_table WHERE username='' ;DROP DATABASE (DB Name) --' and password=''
….其后果可想而知…

四、应对方法

下面我针对JSP,说一下应对方法:

1.(简单又有效的方法)PreparedStatement

采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

使用好处:

(1).代码的可读性和可维护性.

(2).PreparedStatement尽最大可能提高性能.

(3).最重要的一点是极大地提高了安全性.

原理:

sql注入只对sql语句的准备(编译)过程有破坏作用

而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,

而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

2.使用正则表达式过滤传入的参数

要引入的包:

import java.util.regex.*;

正则表达式:

private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;

判断是否匹配:

Pattern.matches(CHECKSQL,targerStr);

下面是具体的正则表达式:

检测SQL meta-characters的正则表达式 :/(\%27)|(\’)|(\-\-)|(\%23)|(#)/ix

修正检测SQL meta-characters的正则表达式 :/((\%3D)|(=))[^\n]*((\%27)|(\’)|(\-\-)|(\%3B)|(:))/i

典型的SQL 注入攻击的正则表达式 :/\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix

检测SQL注入,UNION查询关键字的正则表达式 :/((\%27)|(\’))union/ix(\%27)|(\’)

检测MS SQL Server SQL注入攻击的正则表达式:/exec(\s|\+)+(s|x)p\w+/ix

等等…..

3.字符串过滤

比较通用的一个方法:

(||之间的参数可以根据自己程序的需要添加)

复制代码
public static boolean sql_inj(String str)
{
String inj_str = "'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[] = split(inj_str,"|");
for (int i=0 ; i &lt; inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])&gt;=0)
{
return true;
}
}
return false;
}
复制代码
4.jsp中调用该函数检查是否包函非法字符

防止SQL从URL注入:

sql_inj.java代码:

复制代码
package sql_inj;
import java.net.*;
import java.io.*;
import java.sql.*;
import java.text.*;
import java.lang.String;
public class sql_inj{
public static boolean sql_inj(String str)
{
String inj_str = "'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
//这里的东西还可以自己添加
String[] inj_stra=inj_str.split("\\|");
for (int i=0 ; i &lt; inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])&gt;=0)
{
return true;
}
}
return false;
}
}
复制代码
5.JSP页面判断代码:

使用javascript在客户端进行不安全字符屏蔽

功能介绍:检查是否含有”‘”,”\\”,”/”

参数说明:要检查的字符串

返回值:0:是1:不是

函数名是

复制代码
function check(a)
{
return 1;
fibdn = new Array (”‘” ,”\\”,”/”);
i=fibdn.length;
j=a.length;
for (ii=0; ii<i; ii++)
{ for (jj=0; jj<j; jj++)
{ temp1=a.charAt(jj);
temp2=fibdn[ii];
if (tem’; p1==temp2)
{ return 0; }
}
}
return 1;
}
复制代码
总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了。

凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以 ,切记不要用拼接字符串的方法就可以了。

转载:https://www.cnblogs.com/EasonJim/p/6223216.html
如何防止SQL注入
Web开发中的四个域对象(范围由小到大):

page(jsp有效)  request(一次请求) session(一次会话) application(当前web应用)

page域指的是pageContext.

request域指的是HttpServletRequest

session 域指的是HTTPSession

application 域指的是ServletContext

之所以他们是域对象,原因就是他们都内置了map集合,都有setAttribute getAttribute方法。而且他们的name都是String类型,而value都是Object类型。

他们都有自己固定的生命周期和作用域。

 

这四个对象的生命周期(生命周期就是值对象的创建到销毁的期间):

page:jsp页面被执行,生命周期开始,jsp页面执行完毕,声明周期结束。

request:用户发送一个请求,开始,服务器返回响应,请求结束,生命周期结束。

session:用户打开浏览器访问,创建session(开始),session超时或被声明失效,该对象生命周期结束。

application:web应用加载的时候创建。Web应用被移除或服务器关闭,对象销毁。[结束]。

------------------------------------------------------------------------------------------------------------------------------------------------------------- 

注意:

1.Page只在当前jsp有效,每次请求分别对应不同的request.

2.Request,只在当前请求有效,每次请求分别对应不同的request域

【Request域】可以调用request这个隐含对象的getAttribute()方法来访问具有这种范围类型的对象。也可以使用getParameter(String name) return String来获取XML里传递给它的参数。

String data = "XBY request";
request.setAttribute("data4",data);
request.getRequestDispatcher("/1.jsp").forward(request, response);

Request可以用于Forward

String data = (String)request.getAttribute("data");
out.write(data);

【如果在forward前将在Servlet程序中写入的部分内容已经被真正地传送到客户端,forward方法将抛出IllegalStateException异常。】关键在跳转后要return.
  如果在调用Forward方法前向servlet引擎的缓冲区(response)中写入内容,只要写入到缓冲区的内容还没有真正输出到客户端,forward方法将可以被正常执行,原来写入到缓冲区的内容  会被清空,但是,已经写入到HttpServletResponse对象的响应字段信息保持有效。
  Forward请求转发特点:
   1.客户端只发出了一次请求,而服务器端有多个资源调用
   2.客户端浏览器端RUL不会变化。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
3.Session只在一次会话中有效,会话结束就无法取到数据了。getAttribute(String name) return Object
 HttpSession session = request.getSession();
  session.setAttribute("name", "电视");

  response.setCharacterEncoding("UTF-8");//处理中文乱码问题
  response.setContentType("text/html;charset=UTF-8");//处理中文乱码问题
  PrintWriter out = response.getWriter();//处理中文乱码问题
  
  HttpSession session = request.getSession();
  String product = (String)session.getAttribute("name");
  out.write(product);

    只有当getSession()时,服务器才会为该浏览器创建session,他的生命周期默认为30min。
<session-config>
 <session-timeout>10</session-timeout>
</session-config>
     当使用request.getSession(false);时,就是查看session,不生成session.例如在查看已购买东西时,会使用。//ie8的话,开2个浏览器还是共享一个session,ie7是服务器把sessionid写进了浏览器的进程中,而ie8是服务器实现了多个同一款浏览器的session共享。

 【cookie】如果没有指定Cookies对象的有效期,则Cookies对象只存在于客户端的内存。当浏览器关闭时,Cookies就会失效。
HttpSession session = request.getSession();
  String sessionid = session.getId();
  Cookie cookie = new Cookie("JSESSIONID", sessionid);
  cookie.setPath("/servlet");
  cookie.setMaxAge(30*60);
  response.addCookie(cookie);
  session.setAttribute("name", "电视");//重新写cookie。设置时间。
如果禁用cookie,就是使用利用URL重写技术让浏览器的URL带上SESSIONID。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

4.application:在JSP自动生成的Servlet文件中,是这样定义的:final javax.servlet.ServletContext application;
ServletContext域:

1.这是一个容器

2.说明这个容器的作用范围是整个应用程序范围


public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
   String data="xby ok";
  this.getServletContext().setAttribute("data", data);
  System.out.println("write ok!");
 }

public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
   String value = (String)this.getServletContext().getAttribute("data");
  System.out.println(value);
 }
【补】ServletContext可以转发Servlet,但是Servlet不方便显示。

forward:
String data="xby yes!";
this.getServletContext().setAttribute("data", data);
  
 RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/1.jsp");
 rd.forward(request, response);
      这样不好,因为涉及到多线程问题,ServletContext会被同一应用中的所有Servlet所共享】

      通过ServletContext读取web资源:
InputStream in= this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties props = new Properties();
props.load(in);
  
String username = props.getProperty("username");
String passwd = props.getProperty("passwd");
  

     获得资源文件路径(用于上传下载):
String path= this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
FileInputStream in = new FileInputStream(path);】

    使用ServletContext管理相关的资源。webapp都是在jvm下执行的,所以绝对路径就是在jvm的路径。
ServletContext会在服务器启动时创建,目录在webapps中;服务器停止时会销毁这个ServletContext.------------------------------------------------------------------------------------------------------------------------------------------------------------- -

四个域对象在选择的时候,能用范围小的绝不用范围大的:

page:数据只是暂时存在集合,在jsp页面的其他地方要用,用page(页面中自定义的map)

         (什么时候需要用map了,就用page)

Request:【程序产生数据,数据显示完后就没有用了】
         数据只是做显示的,看完了就没用了。就存request域,请求转发,Servlet产生的处理结果(数据)交给jsp显示。数据转发可以带数据。


Session:【程序产生数据,显示后等会还需要使用】
         数据给用户看完了,一定还要用,会话结束了就没用了

         用户登录,用户信息发给客户端看,看完了,一会访问别的页面还要看用户信息。

         购物车,购物车成功了,给用户看购物车,待会随时间可以查看购物车

         请求重定向,因为是两次请求,每一次请求的数据,第二次请求还要看。

application:【ServletContext在jsp中另一个名字就是application,数据显示后,等会还需要用,还需要给别人用,例如聊天室】
              数据给一个用户用完了,别人还要用;
             聊天室,聊天记录,需要给所有的用户看;统计网站在线人数,所有看到的应该是一个数

【总结】:四个域对象在选择的时候,能用范围小的绝不用范围大的。
1.需要定义Map时不如用page,
2.请求Servlet,转发给jsp的数据存request,
3.请求重定向带过去的数据存Session,
4.全局的数据存application。
4.ServletContext:WEB容器在启动时,他会为每一个【WEB应用程序】都创建一个对应的ServletContext对象,它代表【当前WEB应用】,驻留在服务器的内存里。
在一个contex中的数据都是共享的,它是web应用的配置信息和配置参数。
转载:https://www.cnblogs.com/whytohow/p/5015340.html
解析

4、MySQL乐观锁和悲观锁的概念?原理机制?

悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍。

悲观锁(Pessimistic Lock)

悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。

这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。

乐观锁(Optimistic Lock)

乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。

乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:

复制代码
1. SELECT data AS old_data, version AS old_version FROM …;
2. 根据获取的数据进行业务操作,得到new_data和new_version
3. UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {
    // 乐观锁获取成功,操作完成
} else {
    // 乐观锁获取失败,回滚并重试
}
复制代码
乐观锁是否在事务中其实都是无所谓的,其底层机制是这样:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,直到这一行被成功更新后才释放。因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,即可确认这之间没有发生并发的修改。如果更新失败即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。

总结

乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能

乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方
转载:https://www.cnblogs.com/zhiqian-ali/p/6200874.html
4、MySQL乐观锁和悲观锁的概念?原理机制?

5、jQuery获取元素的方法,至少写出3种。

 eq()     返回带有被选元素的指定索引号的元素
 first()     返回被选元素的第一个元素
 last()     返回被选元素的最后一个元素
next()    返回被选元素的后一个同级元素
prev()    返回被选元素的前一个同级元素
parent()    获取被选元素的父级元素
 摘要:https://www.cnblogs.com/wenJiaQi/p/6136050.html
例子:http://blog.csdn.net/u012102536/article/details/72902175
jQuery获取元素的方法,至少写出3种

6、写出SQL的左连接、右连接、内连接、执行查询过程的关键字。

左连接:left join
右连接:right join
内连接:inner join
执行查询过程:exec  procName;

摘要:http://blog.csdn.net/seanb/article/details/51594234
存储过程摘要:https://www.cnblogs.com/hoojo/archive/2011/07/19/2110862.html
写出SQL的左连接、右连接、内连接、执行查询过程的关键字。

7、Linux命令行。有一个日志文件a.log,计算包含"jd.com"的行数;将文件中的"jd.com"替换成"360buy.com";

有一个日志文件a.log,计算包含"jd.com"的行数;
grep -o 'jd.com' a.log | wc -l
将文件中的"jd.com"替换成"360buy.com";
sed -i "s/jd.com/360buy.com/g"  `grepjd.com -rl /home`  目录文件所有文件替换
 sed -i "s/jd.com/360buy.com/g" 1.txt


摘要:https://www.cnblogs.com/fullhouse/archive/2011/07/17/2108786.html
http://blog.sina.com.cn/s/blog_69f80ee601016rq1.html
https://www.cnblogs.com/end/archive/2012/05/24/2517131.html
将文件中的"jd.com"替换成"360buy.com"

 8、程序题,实现二分法查找。

<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>

void main(){
    int doubleCheck(int a, int b, int c, int d[]);
    int d[] = { 1, 2, 3, 4, 5, 6 };
        doubleCheck(0,5,5,d);
    getchar();

}

void doubleCheck(int a,int b,int c,int d []){//a为数组的下界,b为数组的上界,c为匹配目标,d为查找的范围数组。
    int x = (a + b) / 2;
    //递归的结束条件一定要写在判断条件之前。
    if (d[x] == c)
    {
        printf("%d",x);
    }
    if (d[x] > c)//说明在d[a]-d[x]范围之中
    {
        doubleCheck(a, x-1, c, d);
    }
    if (d[x] < c)
    {
        doubleCheck(x+1, b, c, d);
    }



}</span>
递归实现二分法查找

9、我们负责的一个站点出现无法访问的问题,列举可能导致该问题的原因,并说明如何证明,越多越好。

1、您访问的域名未绑定至主机;
2、您正在使用IP访问;
3、该站点已被网站管理员停止;
4、确认域名是否正确解析
5、万网主机(虚拟机)有时候更改了ip 所以去看看主机ip是否更改
一个站点出现无法访问的问题

 

posted on 2018-01-02 22:30  端着咖啡码农  阅读(6793)  评论(1编辑  收藏  举报