0%

springboot mysql json 使用

  1. 添加@TableName(value = "table_name",autoResultMap = true)

  2. json实体添加@TableField(typeHandler = FastjsonTypeHandler.class)

    1
    2
    3
    4
    5
    6
    7
    @TableName(value = "table_name",autoResultMap = true)
    pulic class TableName{
    @TableField(typeHandler = FastjsonTypeHandler.class)
    private ExtendConfig extendConfig ;//扩展配置
    @TableField(typeHandler = MTableCellListTypeHandler.class)
    private List<Row> rows;
    }

常见问题

  1. 查询时找不到对应字段,因为json序列话问题,不是驼峰,可以通过@JsonProperty(value = "isFiled")解决

  2. 当json数据是jsonArray时,需要自定义json解析器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MTableCellListTypeHandler extends JacksonTypeHandler {
    public MTableCellListTypeHandler(Class<?> type) {
    super(type);
    }
    @Override
    protected Object parse(String json) {
    try {
    return getObjectMapper().readValue(json, new TypeReference<List<Row>>() {});
    } catch (IOException e) {
    throw new RuntimeException(e);
    }
    }
    }

查询(SELECT)

查询employee_id为1,2,3的结果
1
2
3
4
5
6
7
8
9
10
#多条件查询
SELECT * FROM employee WHERE employee.employee_id =1 OR employee.employee_id=2 OR employee.employee_id=3
#范围(1~3)查询
SELECT * FROM employee WHERE employee.employee_id BETWEEN 1 and 3
#半开范围查询
SELECT * FROM employee WHERE employee.employee_id<=3
#截取
SELECT SUBSTRING_INDEX('0-21-3-4', '-', 2); -- 结果:0-21
#截取
SELECT SUBSTRING(SUBSTRING_INDEX('0-21-3-4', '-', 2),3); -- 结果:21

更新(UPDATE)

1
2
3
4
5
-- 更新子查询左连接语句模版
update table_name p left join (
select * from xxx
) m on p.id= m.pp_id
set p.app_id=m.app_id where 1=1 ;

数据库

1. 交叉连接(cross join)

交叉连接(CROSS JOIN):有两种,显式的和隐式的,不带ON子句,返回的是两表的乘积,也叫笛卡尔积

例如:下面的语句1和语句2的结果是相同的。

语句1:隐式的交叉连接,没有CROSS JOIN。

1
2
3
SELECT O.ID, O.ORDER_NUMBER, C.ID, C.NAME
FROM ORDERS O , CUSTOMERS C
WHERE O.ID=1;

语句2:显式的交叉连接,使用CROSS JOIN。

1
2
3
4
SELECT O.ID,O.ORDER_NUMBER,C.ID,
C.NAME
FROM ORDERS O CROSS JOIN CUSTOMERS C
WHERE O.ID=1;

语句1和语句2的结果是相同的,查询结果如下:

a表:

id name
1 张三
2 李四
3 王五

b表:

id job parent_id
1 java 1
2 php 2
3 php 4
1. 内连接(INNER JOIN)

内连接(INNER JOIN):有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。(所谓的链接表就是数据库在做查询形成的中间表)。

显式内连接
1
2
3
SELECT a.*,b.* FROM a INNER JOIN b ON a.id=b.parent_id
//或者
SELECT a.*,b.* FROM a INNER JOIN b WHERE a.id=b.parent_id
隐式内连接
1
SELECT a.*,b.* FROM a,b WHERE a.id=b.parent_id  //只能用where

结果:

id name id1 job parent_id
1 张三 1 java 1
2 李四 2 php 2
2. 左连接(LEFT JOIN)

左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。

1
SELECT a.*,b.* FROM a LEFT JOIN b ON a.id=b.parent_id
id name id1 job parent_id
1 张三 1 java 1
2 李四 2 php 2
3 王五 null null null
3. 右连接(RIGHT JOIN)

右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。

1
SELECT a.*,b.* FROM a RIGHT JOIN b ON a.id=b.parent_id
id name id1 job parent_id
1 张三 1 java 1
2 李四 2 php 2
null null 3 php 4
4.完全连接(FULL JOIN,UNION

完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。

1
2
3
4
5
SELECT a.*,b.* FROM a FULL JOIN b ON a.id=b.parent_id   //MYSQL不支持full join
//可以用union连接左连接和右连接代替full join
SELECT a.*,b.* FROM a LEFT JOIN b ON a.id=b.parent_id
UNION
SELECT a.*,b.* FROM a RIGHT JOIN b ON a.id=b.parent_id
id name id1 job parent_id
1 张三 1 java 1
2 李四 2 php 2
3 王五 null null null
null null 3 php 4
5.交叉连接(CROSS JOIN
1
2
SELECT a.*,b.* FROM a CROSS JOIN b WHERE a.id=b.parent_id
SELECT a.*,b.* FROM a CROSS JOIN b ON a.id=b.parent_id

ON后面的条件(ON条件)和WHERE条件的区别:

  • ON条件:是过滤两个链接表笛卡尔积形成中间表的约束条件。
  • WHERE条件:在有ON条件的SELECT语句中是过滤中间表的约束条件。在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。

从这里可以看出,将WHERE条件移入ON后面是不恰当的。推荐的做法是:
ON只进行连接操作,WHERE只过滤中间表的记录。

总结

  1. 查两表关联列相等的数据用内连接。
  2. Col_L是Col_R的子集时用右外连接。
  3. Col_R是Col_L的子集时用左外连接。
  4. Col_R和Col_L彼此有交集但彼此互不为子集时候用全外。
  5. 求差操作的时候用联合查询。

多个表查询的时候,这些不同的连接类型可以写到一块。例如:

1
2
3
4
5
6
7
8
9
10
11
SELECT T1.C1,T2.CX,T3.CY

FROM TAB1 T1

INNER JOIN TAB2 T2 ON (T1.C1=T2.C2)

INNER JOIN TAB3 T3 ON (T1.C1=T2.C3)

LEFT OUTER JOIN TAB4 ON(T2.C2=T3.C3);

WHERE T1.X >T3.Y;

上面这个SQL查询是多表连接的一个示范。

参考

深入理解MySQL的外连接、内连接、交叉连接

Java就业企业面试问题-数据库(强烈推荐)

Java Web基础

1 Ajax

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 是与服务器交换数据并更新部分网页的艺术(新方法),在不重新加载整个页面的情况下。

1
$.ajax({url:"/jquery/test1.txt",async:false}); //jQuery.ajax([settings])使用方法

2 cookie和session

Cookie是会话技术,将用户的信息保存到浏览器的对象.

Session也是会话技术,将Session的信息保存到服务器的对象.Session是基于Cookie的 利用Cookie向浏览器回写JSessionID.

3 网站大量登陆访问session过多

session默认保存在内存中,内存资源宝贵,session数据量大导致内存利用率高

  • 解决方案:
    1. 设置session超时时间
    2. 将session中的数据序列化到硬盘中
    3. 不使用session,使用cookie(此方法存在安全性问题)

4 Jsp九大内置对象

  • Page:指的是JSP被翻译成Servlet的对象的引用.
  • pageContext:对象可以用来获得其他8个内置对象,还可以作为JSP的域范围对象使用.pageContext中存的值是当前的页面的作用范围》
  • request:代表的是请求对象,可以用于获得客户机的信息,也可以作为域对象来使用,使用request保存的数据在一次请求范围内有效。
  • Session代表的是一次会话,可以用于保存用户的私有的信息,也可以作为域对象使用,使用session保存的数据在一次会话范围有效
  • Application:代表整个应用范围,使用这个对象保存的数据在整个web应用中都有效。
  • Response:是响应对象,代表的是从服务器向浏览器响应数据.
  • Out:out对象被封装为JSPWriter接口,是用于向页面输出内容的对象
  • Config:指的是ServletConfig用于JSP翻译成Servlet后 获得Servlet的配置的对象.
  • Exception:在页面中设置isErrorPage=”true”,即可使用,是Throwable的引用.用来获得页面的错误信息。

参考

Java就业企业面试问题-Java Web(强烈推荐)

SSH基础知识

1 Hibernate

hibernate框架是一个ORM的持久层框架,ORM的含义是对象关系映射,简单理解就是通过对象和关系型数据库之间建立映射信息,以后再操作对象就相当于操作数据库了。hibernate框架是对JDBC进行了轻量级的封装,可以更方便简单的对数据库完成增删改查的操作。同时也提供了查询的方式和查询的策略。例如HQL和QBC的查询方式等。还提供了缓存的策略,效率会更高。

优点
  1. 对象/关系数据库映射(ORM)

    它使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全的面向对象思想

  2. 透明持久化(persistent)

    带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。这些对象可能是普通的JavaBeans/POJO,这个对象没有实现第三方框架或者接口,唯一特殊的是他们正与(仅仅一个)Session相关联。一旦这个Session被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。(例如,用作跟表示层打交道的数据传输对象。)

  3. 事务Transaction(org.hibernate.Transaction)

    应用程序用来指定原子操作单元范围的对象,它是单线程的,生命周期很短。它通过抽象将应用从底层具体的JDBC、JTA以及CORBA事务隔离开。某些情况下,一个Session之内可
    能包含多个Transaction对象。尽管是否使用该对象是可选的,但无论是使用底层的API还是使用Transaction对象,事务边界的开启与关闭是必不可少的。

  4. 它没有侵入性,即所谓的轻量级框架

  5. 移植性会很好

  6. 缓存机制,提供一级缓存和二级缓存

  7. 简洁的HQL编程

缺点
  1. Hibernate在批量数据处理时有弱势
  2. 针对单一对象简单的增删查改,适合于Hibernate,而对于批量的修改,删除,不适合用Hibernate,这也是OR框架的弱点;要使用数据库的特定优化机制的时候,不适合用
  3. 优化策略应用不当会导致大量的资源消耗.
mybatis与hibernate区别
  1. mybatis是把sql语句与java代码分离了,sql语句在xml文件配置的
  2. hibernate是ORM框架,它对jdbc进行了封装,在分层结构中处于持久化层,它能建立面向对象的域模型和关系数据模型之间的映射.它大大简化了dao层的编码工作
  3. mybatis是半自动的,hibernate是全自动的,就是说mybatis可以配置sql语句,对于sql调优来说是比较好的,hibernate会自动生成所有的sql语句,调优不方便,hibernate用起来难度要大于mybatis

2 Spring

优点
  1. Spring能有效地组织你的中间层对象,不管你是否选择使用了EJB。如果你仅仅使用了Struts或其他为J2EE的 API特制的framework,Spring致力于解决剩下的问题。
  2. Spring能消除在许多工程中常见的对Singleton的过多使用。根据我的经验,这是一个很大的问题,它降低了系统的可测试性和面向对象的程度。
  3. 通过一种在不同应用程序和项目间一致的方法来处理配置文件,Spring能消除各种各样自定义格式的属性文件的需要。曾经对某个类要寻找的是哪个魔法般的属性项或系统属性感到不解,为此不得不去读Javadoc甚至源编码?有了Spring,你仅仅需要看看类的JavaBean属性。Inversion of Control的使用(在下面讨论)帮助完成了这种简化。
  1. 通过把对接口编程而不是对类编程的代价几乎减少到没有,Spring能够促进养成好的编程习惯。
  2. Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
  3. 使用Spring构建的应用程序易于单元测试。
  4. Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
  5. Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适用于许多web应用。例如,Spring能使用AOP提供声明性事务管理而不通过EJB容器,如果你仅仅需要与单个数据库打交道,甚至不需要一个JTA实现。
  6. Spring为数据存取提供了一个一致的框架,不论是使用的是JDBC还是O/R mapping产品(如Hibernate)。
Ioc

Inversion of Control 控制反转。

实现IoC的思想就只有两种:依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。

AOP

Aspect Oriented Programming 面向切面编程。

Spring实现面向切面编程使用的是动态代理技术,并且会根据实际情况来选择使用基于子类的还是基于接口的动态代理。

理解
  1. 它的核心之一IoC,降低了我们程序的耦合度,使我们可以把项目设计成为一个可插拔的组件式工程。
  2. 它的另一大核心AOP,使我们在开发过程中,精力得到释放,可以更专注的去理解客户的需求。并且在后期维护时,可以只维护很少的一部分。
  3. 它提供的事务管理机制,采用声明的方式来配置事务,从而在维护时无需改动源码,解决了程序硬编码的弊端。
  4. 它提供的DAO模板使我们的持久层开发又多了一种途径。
  5. 它可以整合其他时下流行的框架,使我们在管理项目时,更加清晰,明确。

3 Struts2

优点
  1. 对框架API和ServletAPI的依赖减少
  2. 可扩展性提高
  3. 框架对插件的可插拔
  4. 拦截器
  5. 可测程度大大提高
缺点
  1. 在并发量比较大的场景中,.每次请求都要创建一个Action,并维护很长的调用链(至少18个拦截器+OGNL解析+Action+Result),资源消耗比较大.
使用场景
  1. SSH对于中小型项目提供了一套完整的解决方案.在表关系相对简单,数据量不大,并发量不高的项目中,能够极大的提高开发效率.
  2. 表关系复杂或数据量比较大时,可以使用Mybatis替换Hibernate.
  3. 并发量很高时可以使用SpringMVC替换struts
框架处理步骤
  1. 客户端初始化一个指向Servlet容器(例如tomcat)的请求
  2. 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
  3. 接着StrutsPrepareAndExecuteFilter被调用,StrutsPrepareAndExecuteFilter询问ActionMapper来解析和判断该次请求是否需要由struts2框架来处理.
  4. 如果ActionMapper判断需要struts2来处理请求,StrutsPrepareAndExecuteFilter会把请求的处理交给ActionProxy
  5. ActionProxy通过Configuration Manager加载框架的配置文件,找到需要调用的Action以及拦截器配置信息
  6. ActionProxy创建一个ActionInvocation的实例。
  7. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
  8. 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果配置。根据配置找到对应的Result处理类来处理结果集.大多数情况输出会交由模版语言(JSP,FreeMarker)完成输出内容拼装

参考

Java就业企业面试问题-ssh框架(强烈推荐)

Java基础

1 重写(Override)与重载(Overload)

  • 重写:父类与子类之间多态性的一种表现(继承重写父类的方法)
  • 重载:多态的具体表现形式(方法名相同,参数不同)

2 接口和抽象

  • 接口:

    1. 一个类可以实现多个接口
    2. 一个接口可以有多个方法
    3. 所有方法必须是抽象方法
    4. 接口不能包含成员变量,除了 static 和 final 变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public interface NameOfInterface
    {
    //接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
    //接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键子。
    //接口中的方法都是公有的。
    //任何类型 final, static 字段
    //抽象方法
    public void eat();
    public void travel();
    }
  • 抽象类(abstract):public abstract class Test{}

    1. 抽象类不能实例化
  • 抽象方法(abstract ): public abstract double function();

    1. 含有抽象方法的类必须是抽象类
    2. 实现类必须重写抽象方法
    3. 构造方法(static)不能抽象。

3 线程

  • 继承Thread
  • 实现Runnable

4 Java集合框架的基本接口

  • collection 接口:最基本的集合接口,一个 Collection 代表一组 Object,Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。
  • list接口:List接口是一个有序的Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的小标)来访问List中的元素,而且允许有相同的元素。
  • set 接口:Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素
  • map接口:将唯一的键映射到值。

5 java中两种异常类型

  • error: 错误,由虚拟机生成并抛出,程序对其不做处理
  • Exception: 异常的父类,需要程序做出处理
  • Runtime Exception: 运行异常,被0除、下标越界等

6 Final、finally、finalize

  • final: 最终,声明类不可继承、方法不可覆盖、属性不可改变

  • finally:是异常处理语句结构的一部分,一定会执行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
    //代码块
    }
    catch (IllegalArgumentException e) {

    }
    finally {
    //Java 中的 Finally 关键一般与try一起使用,在程序进入try块之后,无论程序是因为异常而中止或其它方式返回终止的,finally块的内容一定会被执行 。
    }
  • finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提高垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。

7 序列化(Serializable)

  由于存在于内存中的对象都是暂时的,无法长期驻存,为了把对象的状态保持下来,这时需要把对象写入到磁盘或者其他介质中,这个过程就叫做序列化。实现Serializable接口表示该类可以被序列化。

使用场景:

  • 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候
  • 当你想用套接字在网络上传送对象的时候
  • 当你想通过RMI传输对象的时候

8 设计模式

  • 单例:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  • 工厂:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
  • 模板:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • 装饰:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
  • 代理:为其他对象提供一种代理以控制对这个对象的访问。
  • 适配器:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • 观察者:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

9 阻塞队列(BlockingQueue)

如果容器是空的,取东西会阻塞知道里面有东西,如果是满的,放东西会被阻塞,知道有空间放。

参考

Java就业企业面试问题-Java基础(强烈推荐)

SSm基础知识

1 springMVC

原理

62o0Jg.png

特点

  • 它是基于组件技术的.全部的应用对象,无论控制器和视图,还是业务对象之类的都是java组件.并且和Spring提供的其他基础结构紧密集成.
  • 不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)
  • 可以任意使用各种视图技术,而不仅仅局限于JSP
  • 支持各种请求资源的映射策略
  • 它应是易于扩展的

工作流程

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
  5. 执行处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户

springMVC与struts的区别

  1. springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。
  2. springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
  3. Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

2 SSM,优缺点,使用场景

  1. Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

  2. Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

  3. Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

  4. 总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

3 Mybatis

  1. mybatis配置
  2. SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
  3. mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
  4. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
  5. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
  6. mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
  7. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
  8. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
  9. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

参考

Java就业企业面试问题-ssm框架(强烈推荐)

html转jsp页面样式发生改变

jsp页面DOCTYPE声明不对或者没有声明

修改idea jsp模板

file->settings->Editor->File and Code Templates->Other->jsp files

1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--不加这个样式会发生改变--%>
<!DOCTYPE html>
<html>
<head>
<title>#[[$Title$]]#</title>
</head>
<body>
#[[$END$]]#
</body>
</html>

idea默认jsp模板没有设置DOCTYPE

web2.5默认

3.0默认

html5默认

参考:

html转jsp页面样式发生改变

1.返回普通的json

返回字符串,实体类

三个步骤
  • Jackson jar包是否存在于工程

    1
    2
    3
    4
    // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.8'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.8'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.8.8'
  • <mvc:annotation-driven/> 是否配置(默认配置方案,不支持返回map)

  • 返回方法上面是否添加了@ResponseBody注解。

    1
    2
    3
    4
    5
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    @ResponseBody
    public String test( User user,HttpServletRequest req, HttpServletResponse response){
    return "json数据";
    }

2.map自动转换json ,<mvc:annotation-driven/> 的自定义配置

解决springmvc ResponseBody请求返回406的问题

注意不能用.html后缀

1. 显示层

前端页面login.jsp

InternalResourceViewResolver配置jsp目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎登陆</title>
</head>
<body>
<form id="login" action="<c:url value='/user/login.do'/>" method="post">
<h1>Log In</h1>
<fieldset id="inputs">
<input id="username" name="name" type="text" placeholder="Username" autofocus required>
<input id="password" name="password" type="password" placeholder="Password" required>
</fieldset>
<fieldset id="actions">
<input type="submit" id="submit" value="Log in">
<a href="">Forgot your password?</a><a href="">Register</a>
</fieldset>
</form>
</body>
</html>

前端控制层UserController.java

spring-mvc.xml配置<context:component-scan base-package="com.xuan.user.controller"/>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Controller
@RequestMapping(value = "user")
public class UserController {
@Resource
private UserService userService;
@RequestMapping(value = "/login",method = RequestMethod.POST)
public ModelAndView login(User user, HttpServletRequest req) {
ModelAndView modelAndView = new ModelAndView("index");
if (user == null) {
return new ModelAndView("login").addObject("message", "登陆信息不能为空!");
}
if (StringUtils.isEmpty(user.getName()) || StringUtils.isEmpty(user.getPassword())){
return new ModelAndView("login").addObject("message", "用户名或密码不能为空!");
}
user = userService.login(user);
modelAndView.addObject("user", user);
return modelAndView;
}
}

2.业务控制层

service接口层

业务接口UserService.java

1
2
3
public interface UserService {
public User login(User user);
}

service接口实现层(impl)

业务实现UserServiceImpl.java

1
2
3
4
5
6
7
8
9
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource
private UserDao userDao;
@Override
public User login(User user) {
return userDao.findByUser(user);
}
}

3.持久层

spring-beans.xml配置MapperScannerConfigurer

1
<context:component-scan base-package="com.xuan"/>

接口层UserDao.jva

1
2
3
4
@Repository //注册为持久层的bean
public interface UserDao {
User findByUser(@Param("user") User user);
}

sqlmapper数据库语句

spring-bean.xml配置SqlSessionFactoryBean

userMapper.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace的值就是dao接口的完整路劲,就这个demo而言namespace 就是TestDao.java的完整路劲 -->
<mapper namespace="com.xuan.user.dao.UserDao">
<select id="findByUser" parameterType="com.xuan.user.model.User" resultType="com.xuan.user.model.User">
SELECT * FROM x_user WHERE (`name`=#{user.name} OR `email`=#{user.email} OR `phone`=#{user.phone}) AND `password`=#{user.password};
</select>
</mapper>

4. 实体

model实体层

mybatis-conf.xml配置<typeAliases><package name="com.xuan.user.model"/></typeAliases>

实体类User.java

1
2
3
4
5
6
public class User(){
.....
private String name;
private String password;
.....
}

1. 新建项目ssm_template

creat project->gradle{java+web}->{GroupId:com.xuan;artifactId:ssm_template}->next->finsh

2. 创建项目目录和文件

根目录/ 描述
src/main/webapp/WEB-INF/web.xml Project Structure->Modules->+ssm_template->ssm_template_main->Web Gradle...->{点击+web.xml:src\main\webapp\WEB-INF\web.xml}[^1]
src/main/java Mark as: Sources(默认是,不用配置),java代码目录
src/main/resources Mark as: Resources(默认是,不用配置),配置资源文件目录
src/main/resources/config 配置文件目录(例如:spring-mvc.xml)
src/main/resources/sqlMapper 数据库语句配置目录
src/main/java/com.xuan/dao 数据库接口层
src/main/java/com.xuan/controller

[^1]: 勾上source root{…/resources,…/java}配置Artifacts,删除Web Application:Exploded下红色的目录

3.配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<servlet>
<!--名称 -->
<servlet-name>dispatcher</servlet-name>
<!-- Servlet类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-mvc.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被dispatcher拦截 -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

4. 配置build.gradle

导入相关的ssm包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apply plugin: 'groovy'  //+
apply plugin: 'idea' //+
dependencies {
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.7'
compile group: 'javax.servlet', name: 'jstl', version: '1.2'
// Spring
compile group: 'org.springframework', name: 'spring-core', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-web', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-jdbc', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-aop', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-beans', version: '4.3.4.RELEASE'
compile group: 'org.springframework', name: 'spring-test', version: '4.3.4.RELEASE'
// MyBatis
compile group: 'org.mybatis', name: 'mybatis', version: '3.4.1'
compile group: 'org.mybatis', name: 'mybatis-spring', version: '1.3.0'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.40'
// junit
compile group: 'junit', name: 'junit', version: '4.12'
}

5. 配置spring-mvc.xml

右键new spring config需要先导包才能直接new

路径:/src/main/resources/config/spring-mvc.xml

project structure配置:Create Spring facet spring mvc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 自动扫描控制器,实现支持注解的IOC ,设置要扫描的包,一般含controller类的包(解释有问题,不扫描dao,会提示错误,但不影响运行)-->
<context:component-scan base-package="com.xuan"/>
<!-- Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler/>

<!-- 支持mvc注解驱动,控制器映射器和控制器适配器 -->
<mvc:annotation-driven/>

<!--静态文件访问权限配置(静态资源映射器)-->
<mvc:resources mapping="statics/**" location="/WEB-INF/"/>

<!-- 视图解析器 -->
<bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀,设置页面的目录 -->
<property name="prefix" value="/"/>
<!-- 后缀,页面的后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<import resource="spring-mybatis.xml"/>

6. 配置spring-mybatis.xml

右键new spring config

路径:/src/main/resources/config/spring-mybatis.xml

project structure配置:Create Spring facet spring mybatis parent contestspring mvc

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
33
34
35
36
37
38
39
<!--加载jdbc文件-->
<context:property-placeholder location="classpath:config/jdbc-mysql.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<!-- 配置Session工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 加载mybatis-config.xml文件,mybatis配置文件路径 -->
<property name="configLocation" value=""/>
<!--自动扫描需要定义类别名的包,将包内的JAVA类的类名作为类别名-->
<property name="typeAliasesPackage" value="com.xuan.model"/>

<!-- 指定实体类映射文件,可以指定同时指定某一包以及子包下面的所有配置文件,可以直接指定文件 -->
<property name="mapperLocations" value="classpath:sqlMapper/*.xml"/>
</bean>

<!--动态代理实现 不用写dao的实现 -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 这里的basePackage 指定了dao层接口路劲,这里的dao接口不用自己实现 -->
<property name="basePackage" value="com.xuan.dao"/>
<!-- 如果只有一个数据源的话可以不用指定,但是如果有多个数据源的话必须要指定 -->
<!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> -->
<!--直接指定了sqlsessionTemplate名称,这个和上面的其实是一样的 -->
<!-- <property name="sqlSessionTemplateBeanName" value="sqlSession" /> -->
</bean>

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 使用全注释事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

7. 配置jdbc-mysql.properties

1
2
3
4
5
6
7
8
9
10
# 将jdbc.jarDirection后的内容更改为gradle下载的
# mysql-connector-java-5.1.x.jar所在的路径,gradle自动下载的路径如下所示(未使用)
jdbc.jarDirection=/Users/xuan/.gradle/caches/modules-2/files-2.1/mysql\
/mysql-connector-java/5.1.40/ef2a2ceab1735eaaae0b5d1cccf574fb7c6e1c52/\
mysql-connector-java-5.1.40.jar
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_template?\
useUnicode=true&characterEncoding=UTF-8&useSSL=false
jdbc.username=root
jdbc.password=root

8. 创建数据库ssm_template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE DATABASE /*!32312 IF NOT EXISTS*/`ssm_template` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `ssm_template`;

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for ssm_test
-- ----------------------------
DROP TABLE IF EXISTS `ssm_test`;
CREATE TABLE `ssm_test` (
`name` varchar(255) DEFAULT NULL,
`value` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of ssm_test
-- ----------------------------
INSERT INTO `ssm_test` VALUES ('ssm', 'ssm框架搭建完成');

9. 测试相关文件

index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="test">点击测试ssm框架</a>
<br>
name:${ssmTest.name}
<br>
value:${ssmTest.value}
</body>
</html>
SsmTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SsmTest {
String name;
String value;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}
SsmTestDao.java
1
2
3
4
@Repository
public interface SsmTestDao {
SsmTest getSsm(String name);
}
TestController.java
1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class TestController {
@Resource
private SsmTestDao ssmTestDao;
@RequestMapping("test")
public String totestPage(Model model){
SsmTest ssmTest= ssmTestDao.getSsm("ssm");
System.out.printf(""+ssmTest.getValue()+","+ssmTest.getName());
model.addAttribute("ssmTest",ssmTest);
return "index";
}
}
ssm_test.xml
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8" ?>
<!--doctype必须加-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace的值就是dao接口的完整路劲,就这个demo而言namespace 就是TestDao.java的完整路劲 -->
<mapper namespace="com.xuan.dao.SsmTestDao">
<!-- 这里的id就是接口中方法的名称,resulType,返回的bean,这里为String -->
<select id="getSsm" parameterType="String" resultType="com.xuan.model.SsmTest">
SELECT * FROM ssm_test WHERE name= #{name}
</select>
</mapper>

相关配置截图

62IMgs.png
62IK3j.png
62IeUS.png
62IuCQ.png
62Im4g.png
62IQvn.png
62I1uq.png

项目地址:

https://github.com/xuanfong1/ssm_template

如果运行不起,注意out目录,删除重试