Java Web总结

JSP与Servlet的区别

JSP与Servlet的区别

Servlet的生命周期

Servlet的接口

前三个方法与Servlet的生命周期相关,Web容器加载Servlet并将其实例化之后,Servlet的生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servlet的service()方法,service()方法根据需要调用与请求相对应的doGet()或doPost()方法;当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用destroy()方法

如何保持会话状态,有哪些方式,区别如何?

  • URL重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以表示一个会话
  • 设置表单隐藏域:将和会话跟踪相关的字段添加到隐藏表单域中,这些信息不回在浏览器中显示但是在提交表单时会提交给服务器

以上两种方式都比较难以处理跨越多个页面的信息传递,因为如果每次都要修改URL或者在页面添加隐藏表单域来存储用户会话相关的信息,会变得比较复杂。

HTML5中可以使用Web Storage技术通过JavaScript来保持数据,例如可以使用localStoragesessionStorage来保存用户会话的信息,它能够实现会话跟踪

cookie和session的区别

由于http协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是session。这个session是保存在服务端的,有一个唯一标识。在服务端保存session的方法有很多,内存、数据库、文件都可以。

每次http请求的时候,客户端都会发送相应的cookie信息到服务端,实际上大多数的应用都是用cookie来实现session跟踪的,第一次创建session的时候,服务端会在http协议中告诉客户端,需要在cookie里面记录一个session id,以后每次请求把这个会话id发送到服务器。

如果客户端浏览器禁用了cookie,在这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次http请求,URL后面都会附上一个诸如sid=xxx这样的参数,服务端据此来标识用户。

总结:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。

Spring IOC和AOP

  1. Spring IOC

    IOC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IOC更简单的诠释。**控制反转是把传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的控制反转就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建并管理对象之间的依赖关系。**DI是对IOC更准确的描述,即组件之间的依赖关系由容器在运行期间决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

    举个例子:类A需要用到接口B中的方法,那么就需要类A与接口B建立关联或者依赖关系,最原始的方法就在在类A创建接口B的实现类C的实例,但**这种方法要求开发人员自行维护两者的依赖关系,即当依赖关系需要改变的时候需要修改代码并重新构建整个系统。**如果通过一个容器来管理这些对象的依赖关系,只需要在类A中定义好用于管理接口B的方法(构造器或者setter方法),将类A与接口B的实现类C放入容器,通过对容器的配置来实现两者的关系。

    Spring IOC实现原理

  2. Spring AOP

    AOP(Aspect-Oriented Programming)指一种程序设计范式,该范式以一种称为切面(aspect)的语言构造为基础,**切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点。**通常,事务、日志、安全性等关注就是应用中的横切关注功能。

    Spring+AOP实现原理

  3. IOC容器的加载过程

    • 创建IOC配置文件的抽象资源
    • 创建一个BeanFactory
    • 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory
    • 把定义好的资源位置读入配置信息,具体解析过程有XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程
  4. 动态代理与cglib实现的区别

    • JDK动态代理只能对实现了接口的类生成代理,而不能针对类
    • CGLIB是针对类实现代理,主要是对指定的类生成了一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final
    • JDK代理是不需要第三方库,只要JDK环境就可以进行代理
    • CGLib必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承

Spring MVC的原理

Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。两个核心是:

  • **处理器映射:**选择使用哪个控制器来处理请求
  • **视图解析器:**选择结果应该如何渲染

通过以上两点,Spring MVC保证了如何选择控制处理请求和如何选择视图展现输出之间的松耦合。

Spring MVC运行原理

Mybatis

  1. #{}和${}的区别是什么?

    1
    2
    3
    4
    #{}是预编译处理,${}是字符串替换
    Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值
    Mybatis在处理${}时,就是把${}替换成变量的值
    使用#{}可以有效的防止SQL注入,提高系统安全性
  2. 当实体类中的属性名和表中字段名不一样,怎么办?

    1
    2
    3
    4
    第一种:通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
    <select id="selectorder" paramaterType="int" resultType="me.gacl.domain.order">
    select order_id id, order_no orderno, order_price price from orders where order_id=#{id};
    </select>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    第二种:通过<resultMap>来映射字段名和实体类属性名的一一对应的关系
    <select id="getOrder" parameterType="int" resultType="orderResultMap">
    select * from orders where order_id=#{id};
    </select>
    <resultMap type="me.gacl.domain.order" id="orderResultMap">
    <!-用id属性来映射主键字段->
    <id property="id" column="order_id">
    <!-用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性->
    <result property="orderno" column="order_no"/>
    <result property="price" column="order_price"/>
    </resultMap>
  3. 模糊查询like语句该怎么写?

    1
    2
    3
    4
    5
    6
    7
    第一种:在Java代码中添加sql通配符
    String wildCardName = "%smi%";
    list<name> names = mapper.selectlike(wildCardName);

    <select id = "selectlike">
    select * from foo where bar like #{value}
    </select>
    1
    2
    3
    4
    5
    6
    7
    第2种:在sql语句中拼接通配符,会引起sql注入
    String wildCardName = "smi";
    list<name> names = mapper.selectlike(wildCardName);

    <select id="selectlike">
    select * from foo where bar like "%"#{value}"%"
    </select>
    1
    2
    3
    4
    5
    第3种:使用动态SQL语句,OGNL表达式中的bind标签
    <select id="selectEmployLikeName" resultType="org.fkit.domain.Employee">
    <bind name="pattern" value="'%' + _parameter.getName() + '%'" />
    select * from tb_employee where loginname like #{pattern}
    </select>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 根据传入的参数进行模糊查询
    List<Employee> selectEmployeeLikeName(Employee employee);

    public void test(SqlSession session) {
    EmployeeMapper em = session.getMapper(EmployeeMapper.class);
    Employee employee = new Employee();
    // 设置模糊查询的参数
    employee.setName("o");
    List<Employee> list = em.selectEmployeeLikeName(employee);
    System.out.println(list);
    }
  4. 通常一个xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
    答:Dao接口,就是人们通常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,就是传递给sql的参数。Mapper接口没有实现类,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:

    1
    com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个<select><insert><update><delete>标签,都会被解析为一个MappedStatement对象

    Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
    Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截方法接口,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

  5. Mybatis是如何将sql执行结果封装成目标对象并返回的?都有哪些映射形式?
    答:第一种是使用标签,逐一定义列名和对象属性名之间的映射关系;第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。

    有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

  6. Mybatis是如何进行分页的?分页插件的原理是什么?
    答:Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

    分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

  7. 如何执行批量插入?
    首先,创建一个简单的insert语句:

    1
    2
    3
    <insert id="insertname">
    insert into names (name) values (#{value})
    </insert>

    然后在Java代码中像下面这样执行批处理插入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    List<string> names = new ArrayList<>(); 
    names.add(“fred”);
    names.add(“barney”);
    names.add(“betty”);
    names.add(“wilma”);

    // 注意这里 executortype.batch
    sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);
    try {
    namemapper mapper = sqlsession.getmapper(namemapper.class);
    for (string name : names) {
    mapper.insertname(name);
    }
    sqlsession.commit();
    } finally {
    sqlsession.close();
    }
  8. 如何获取自动生成的(主)键值?
    答:insert方法总是返回一个int值,这个值代表的是插入的行数。而自动生成的键值在insert方法执行完后可以被设置到传入的参数对象中。示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <insert id="insertname" useGeneratedkeys="true" keyProperty="id">
    insert into name (name) values (#{name})
    </insert>

    name name = new name();
    name.setName("fred");

    int rows = mapper.insertname(name);
    System.out.println("row inserted=" + rows);
    System.out.println("generated key value=" + name.getId());
  9. 在mapper中如何传递多个参数?
    第一种:

    1
    2
    3
    4
    5
    6
    7
    # Dao层的函数
    public selectUser(String name, String area);

    # 对应的xml,#{0}代表接收的是dao层的第一个参数,#{1}代表dao层中第二个参数,更多参数一致往后即可。
    <select id="selectUser" resultMap="BaseResultMap">
    select * from user_user_t where user_name=#{0} and user_area=#{1}
    </select>

    第二种:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 使用@param注解
    import org.apache.ibatis.annotations.param;

    public interface userMapper(user selectUser(@param("userName") String userName, @param("hashedPassword") String hashedPassword));

    # 然后就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递个mapper)
    <select id="selectUser" resultType="user">
    select id, username, hashedPassword from some_table where userName=#{userName} and hashedPassword=#{hashedPassword}
    </select>
  10. Mybatis动态sql是做什么?都有哪些动态sql?能简述一下动态sql的执行原理不?
    答:Mybatis的动态sql可以让我们在xml映射文件内,以标签形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
    Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind
    其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。

  11. Mybatis的xml映射文件中,不同的xml映射文件,id是否可以重复?
    答:不同的xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;毕竟namespace不是必须的,只是最佳实践而已。
    原因就是namespace+id是作为Map<String, MappedStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据相互覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

  12. 为什么说Mybatis是半自动的ORM映射工具?它与全自动的区别在哪里?
    答:Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
    Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。

  13. 一对一、一对多的关联查询?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    <mapper namespace="com.lcb.mapping.userMapper">
    <!--association 一对一关联查询-->
    <select id="getClass" parameterType="int" resultMap="ClassesResultMap">
    select * from class c, teacher t where c.teacher_id=t.id and c.c_id=#{id}
    </select>
    <resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
    <!--实体类的字段名和数据表的字段名映射-->
    <id property="id" column="c_id"/>
    <result property="name" column="c_name"/>
    <association property="teacher" javaType="com.lcb.user.Teacher">
    <id property="name" column="t_id"/>
    <result property="name" column="t_name">
    </association>
    </resultMap>

    <!--collection 一对多关联查询-->
    <select id="getClass2" parameter="int" resultMap="ClassesResultMap2">
    select * from class c, teacher t, student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
    </select>
    <resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
    <id property="id" column="c_id"/>
    <result property="name" column="c_name"/>
    <association property="teacher" javaType="com.lcb.user.Teacher">
    <id property="id" column="t_id"/>
    <result property="name" column="t_name"/>
    </association>
    <collection property="student" ofType="com.lcb.user.Student">
    <id property="id" column="s_id"/>
    <result property="name" column="s_name"/>
    </collection>
    </resultMap>
    </mapper>
Author: Toyan
Link: https://toyan.top/java-web-summary/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
支付宝打赏
微信打赏