0%

2018年2月26日 下午8:51

service平级调用

  1. 在ProductServiceImpl.java本身是一个service类,但是其中也使用了iCategoryService这个service
  2. 由于本身service就是给controller使用直接返回给页面的responseService对象,当service去使用另一个service的返回responseService时,我们就可能需要考虑一个类型转换的问题
    ProductServiceImpl.java
  3. 解决方法: 给这个方法加上强制类型转换

2018年2月26日 下午8:51

关于responseService

  1. 在这个项目中,responseService因为是泛型类,所以,有responseService的地方就应该写成responseService,T是具体的类型。
  2. 但是我们可以看到,有的写了有的没写
  3. 我的理解是最好写上,有些情况下是不写代码也是正常运行。但是我们一遇到报错的情况,就必须写了。

泛型

  1. 泛型的语法:Java中的泛型方法 - 杨元 - 博客园

  2. 是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。JAVA中的泛型用法一种: 返回值用法。_百度知道
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.mmall.common;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonSerialize;

import java.io.Serializable;

/**
* Created by geely
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
//保证序列化json的时候,如果是null的对象,key也会消失
public class ServerResponse<T> implements Serializable {

private int status;
private String msg;
private T data;

private ServerResponse(int status){
this.status = status;
}
private ServerResponse(int status,T data){
this.status = status;
this.data = data;
}

private ServerResponse(int status,String msg,T data){
this.status = status;
this.msg = msg;
this.data = data;
}

private ServerResponse(int status,String msg){
this.status = status;
this.msg = msg;
}

@JsonIgnore
//使之不在json序列化结果当中
public boolean isSuccess(){
return this.status == ResponseCode.SUCCESS.getCode();
}

public int getStatus(){
return status;
}
public T getData(){
return data;
}
public String getMsg(){
return msg;
}


public static <T> ServerResponse<T> createBySuccess(){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode());
}

public static <T> ServerResponse<T> createBySuccessMessage(String msg){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),msg);
}

public static <T> ServerResponse<T> createBySuccess(T data){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),data);
}

public static <T> ServerResponse<T> createBySuccess(String msg,T data){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),msg,data);
}

public static <T> ServerResponse<T> createByError(){
return new ServerResponse<T>(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getDesc());
}


public static <T> ServerResponse<T> createByErrorMessage(String errorMessage){
return new ServerResponse<T>(ResponseCode.ERROR.getCode(),errorMessage);
}

public static <T> ServerResponse<T> createByErrorCodeMessage(int errorCode,String errorMessage){
return new ServerResponse<T>(errorCode,errorMessage);
}
}

2018年2月25日 下午9:03

后来补充

关于spring-mvc的可以简单的看一下应用intellij IDEA创建SpringMVC项目,SpringMVC数据绑定入门教程-慕课网

web.xml

SpringMVC的配置:Dispatcher-servlet.xml

mvc:annotation-driven标签的说明:
SpringMVC-mvc:annotation-driven的作用 - jacker - CSDN博客这篇文章最后

spring的配置文件

spring的总配置文件:applicationContent.xml

spring的配置文件:applicationContent-datasource.xml

2018年2月25日 下午8:08

JavaWeb三大组件(Servlet、Filter、Listener) - CSDN博客

阶段概述:

  1. servlet阶段:将URL请求能够通过web.xml的配置,映射URL到一个具体的servlet类但是他不能映射到方法,所以,在selvet中我们还得通过具体的URL参数去手工敲码,跳向某个方法
  2. 基于servlet的MVC模式实现
    1. 这个主要是想用于和SpringMVC进行比较,就能清晰的知道SpringMVC到底做了什么。
    2. 代码在附录中
  3. SpringMVC牛逼的地方有:
    1. URL直接映射到方法,而不是仅仅是类,并且这个类也不是servlet了,就是一个普通给的类,只不过加上了@controller
    2. controller中操作service对象的方式
      1. 商品管理第四个知识点
    3. 从controller对于的方法执行完之后,跳转到jsp页面的方式
      1. 通过modelAndView
      2. 可以和基于servlet的MVC模式实现对比
    4. 代码实例:
      1. SpringMVC 基础教程 简单入门实例 - CSDN博客

附录:servlet的MVC模式实现

servlet的MVC模式实现目录结构:

EmployeeServlet.java

EmployeeServiceImpl.java

EmployeeService.java:就是接口而已

SuperDaoImpl.java:老师封装好的dao

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
package com.shanxi.weixin.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.shanxi.weixin.dbUtils.DbUtils;

public class SuperDaoImpl implements SuperDao {


@Override
public List<Map<String, Object>> queryForList(String sql) {
List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
try {
Connection conn = DbUtils.getConnection();
Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery(sql);
list = rsToList(rs);
DbUtils.close();
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}


@Override
public int batchDelete(String sql, String[] ID) {
Connection conn = DbUtils.getConnection();
try {
PreparedStatement ps = conn.prepareStatement(sql);
if (ID.length>0){
for(int i=0;i<ID.length;i++){
ps.setInt(1,Integer.parseInt(ID[i]));
ps.addBatch();
}
}
ps.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}


@Override
public List<Map<String, Object>> queryForList(String sql, int[] types, Object[] obj) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
Connection conn = DbUtils.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
switch (types[i]) {
case Types.INTEGER:
ps.setInt(i+1,Integer.parseInt(obj[i].toString()));
break;
case Types.VARCHAR:
ps.setString(i+1,obj[i].toString());
break;
default:
ps.setString(i+1,obj[i].toString());
}
}
ResultSet rs = ps.executeQuery();
list = rsToList(rs);
DbUtils.close();

} catch (SQLException e) {
e.printStackTrace();
}

return list;
}

@Override
public Map<String, Object> queryForMap(String sql) {
List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
try {

Connection conn = DbUtils.getConnection();
Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery(sql);
list = rsToList(rs);
DbUtils.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(!list.isEmpty()){
return list.get(0);
}
return null;
}
@Override
public Map<String, Object> queryForMap(String sql, int[] types, Object[] obj) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
Connection conn = DbUtils.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
switch (types[i]) {
case Types.INTEGER:
ps.setInt(i+1,Integer.parseInt(obj[i].toString()));
break;
case Types.VARCHAR:
ps.setString(i+1,obj[i].toString());
break;
default:
ps.setString(i+1,obj[i].toString());
}
}
ResultSet rs = ps.executeQuery();
list = rsToList(rs);
DbUtils.close();

} catch (SQLException e) {
e.printStackTrace();
}
if(!list.isEmpty()){
return list.get(0);
}
return null;
}

@Override
public int excuteUpdate(String sql) {
try {
Connection conn = DbUtils.getConnection();
Statement sta = conn.createStatement();
int count = sta.executeUpdate(sql);
DbUtils.close();
return count;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

@Override
public int[] deleteDept(String sql1, String sql2) {
try {
int[] count = new int[2];
Connection conn = DbUtils.getConnection();
conn.setAutoCommit(false);
Statement sta = conn.createStatement();
int count1 = sta.executeUpdate(sql1);
count[0] = count1;
int count2 = sta.executeUpdate(sql2);
count[1] = count2;
conn.commit();
DbUtils.close();
return count;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

@Override
public int excuteUpdate(String sql, int[] types, Object[] obj) {
try {
Connection conn = DbUtils.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
switch (types[i]) {
case Types.INTEGER:
ps.setInt(i+1,Integer.parseInt(obj[i].toString()));
break;
case Types.VARCHAR:
ps.setString(i+1,obj[i].toString());
break;
default:
ps.setString(i+1,obj[i].toString());
}
}
int count = ps.executeUpdate();
DbUtils.close();
return count;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

@Override
public int queryForCount(String sql) {
try {
Connection conn = DbUtils.getConnection();
Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery(sql);
int count = 0 ;
while(rs.next()){
count = rs.getInt(1);
}
DbUtils.close();
return count;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

@Override
public int queryForCount(String sql, int[] types, Object[] obj) {
try {
Connection conn = DbUtils.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
switch (types[i]) {
case Types.INTEGER:
ps.setInt(i+1,Integer.parseInt(obj[i].toString()));
break;
case Types.VARCHAR:
ps.setString(i+1,obj[i].toString());
break;
default:
ps.setString(i+1,obj[i].toString());
}
}
ResultSet rs = ps.executeQuery();
int count = 0;
while(rs.next()){
count = rs.getInt(1);
}
DbUtils.close();
return count;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

private List<Map<String, Object>> rsToList(ResultSet rs) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
while(rs.next()){
Map<String, Object> map = new HashMap<String,Object>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
switch (rs.getMetaData().getColumnType(i)) {
case Types.INTEGER:
map.put(rs.getMetaData().getColumnName(i),rs.getInt(i));
break;
case Types.VARCHAR:
map.put(rs.getMetaData().getColumnName(i),rs.getString(i));
break;
default:
map.put(rs.getMetaData().getColumnName(i),rs.getObject(i));
}
}
list.add(map);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}



}

2018年2月25日 下午7:28

  1. 首先,需要说明的是:myBatis-generator只是再mybatis的基础上使之自动化
  2. 自动化的内容有:
    1. 自动生成resource_mappers_*Mapper.xml
    2. 自动生成pojo/下各种与数据表直接对应的java实体类
    3. 自动生成dao/*Mapper.java接口类,用于执行sql语句
      1. 这点可以说是myBatis-generator最新颖的地方
      2. 我们最原始的mybatis方式是使用sqlSession对象去执行具体的sql语句
      3. 但在myBatis-generator中sqlSession就像不存在一样,对于用户来说就暴露了一个dao/Mapper.java接口类,通过接口类去执行需要的sql语句*

这里可以参考mybatis 三剑客

使用SpringMVC之后,融合myBatis-generator的方式

MyBatis使用和配置详解中我们知道,sqlSession这个对象是用是最终要用于执行sql语句的对象,但在myBatis-generator

2018年2月25日 下午6:57

项目结构

MyBatis的重要依赖包

  1. myBatis-3.2.3.jar
  2. Mysql-connector-java-5.1.34.jar
    配置文件(xml)
  3. TeacherMapper.xml
  4. StudentMapper.xml
  5. Reource.xml

配置文件详解:

TeacherMapper.xml


解析:

  1. 本质:将sql语句与代码进行分离,方便管理
  2. 绿色:是命名空间,是找到TeacherMapper.xml的关键标识,对应于测试代码TeacherEntity teacherEntity=sqlSession.selectOne("teacher.selectTeacherOne", "804”);中的teacher
  3. 红色:是一个对应于*Entity.java实体的xml表示
  4. 红色

source.xml


解析:

  1. 红色:是连接数据库的各种配置信息,用于登录数据库
  2. 绿色:是用于声明项目中实体类对应的xml配置文件有哪些

实体类

本质就是对应于数据库表字段的get,set方法

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.pan.teacher;

import java.io.Serializable;
import java.util.List;

import com.pan.test.StudentEntity;

public class TeacherEntity implements Serializable{

/**
*
*/
private static final long serialVersionUID = 1L;
private String t_id;
private String t_name;
private String t_sex;
private String t_birthday;
private String prof;
private String depart;
private List<StudentEntity> studentList;
public String getT_id() {
return t_id;
}
public void setT_id(String t_id) {
this.t_id = t_id;
}
public String getT_name() {
return t_name;
}
public void setT_name(String t_name) {
this.t_name = t_name;
}
public String getT_sex() {
return t_sex;
}
public void setT_sex(String t_sex) {
this.t_sex = t_sex;
}
public String getT_birthday() {
return t_birthday;
}
public void setT_birthday(String t_birthday) {
this.t_birthday = t_birthday;
}
public String getProf() {
return prof;
}
public void setProf(String prof) {
this.prof = prof;
}
public String getDepart() {
return depart;
}
public void setDepart(String depart) {
this.depart = depart;
}
public List<StudentEntity> getStudentList() {
return studentList;
}
public void setStudentList(List<StudentEntity> studentList) {
this.studentList = studentList;
}

}

测试

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
package com.pan.teacher;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.pan.test.StudentEntity;

public class TeacherTest {

public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub

//读取myBatis的核心配置文件
Reader reader=Resources.getResourceAsReader("reource.xml");
//创建二级缓存
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
//创建一级缓存
SqlSession sqlSession=sessionFactory.openSession();

//-------------------级联查询----------------
//注意:在myBatis中只有级联查询,没有级联增删改
TeacherEntity teacherEntity=sqlSession.selectOne("teacher.selectTeacherOne", "804");
System.out.println(teacherEntity.getT_name());
List<StudentEntity> list=teacherEntity.getStudentList();
System.out.println(list.size());
}

}

2018年2月25日 下午6:10

JDBC:
JDBC,通过属性配置文件封装DbUtiles类

连接池:
两种数据库连接池 (2017/9/5)
C3P0连接池配置和实现详解 - CSDN博客
DBCP数据库连接池的简单使用 - sunseine - 博客园

mybatis:
MyBatis使用和配置详解

mybatis-generator:
myBatis-generator理解
mybatis 三剑客

2018年2月24日 下午9:17

学习目标一:与实现vo相关

  1. 抽象POJO、BO、VO对象之间的转换关系及解决思路
    1. 在一期中,我们只使用vo(value object),不用bo(business object)
    2. 效果:ServiceResponse以前中data对象保存的是POJO_Product对象,现在保存的是vo_ProductDetailVo。
    3. 本质:vo\ProductDetailVo对象比POJO\Product对象多几个属性而已,最终呈现在结构接口中的数据更多而已
    4. 为啥不直接更改POJO中的Product?
      1. POJO是Mybatis-generator自动生成的,与数据库是一一对应的,我们最好不要打破这种一一对应的关系

知识点的理解

下面的两个知识点静态块+流读取Properties配置文件,都是在由于我么要使用vo这种抽象对象,其中有一个新的属性:imageHost。效果如下:

我们期望达到的目标是:

  1. 防止硬编码,让配置与代码分离
    1. 如果仅仅是为了防止硬编码,那么我们可以使用static或者使用枚举类去实现。
  2. 为了以后可以进行热部署
    1. 有了这条,我们就必须使用properties配置文件来实现分离的目的

接下来详细解释着两个知识点:

  1. 静态块
    1. 作用:初始化静态变量,在类被加载的时候执行,而不是等到方法调用的时候
    2. 启动顺序:静态块>普通代码块>构造代码块
    3. 启动时间:在类被加载的时候执行,且只执行一次
  2. 流读取Properties配置文件
    1. 作用:读取Properties配置文件
    2. 代码位置:
    3. Properties配置文件位置:
      1. resource/mmall.properties

学习目标二: joda-time

  1. joda-time快速入门
    1. 用于封装util/DateTimeUtil工具类

学习目标三:Mybatis-PageHelper

page-helper

学习目标四:IoC控制反转,依赖注入

控制反转

学习目标五:Mybatis对where语句动态拼装的几个版本的演变

自动导入包:alt+enter

Tomcat启动的时候就需要读取配置

三种方法处理配置型变量

  1. enum
  2. static
  3. property

2018年2月24日 下午3:32

学习目标:

  1. 如何实际及封装无线层级的树状数据结构
  2. 递归算法的设计思想

注意我红框框出的内容
4. 如何处理复杂对象排重
1. 使用set集合
5. 重写hashcode和equal的注意事项
1. 缘由:当我们使用set这样的语法去排重时,我们需要重新写Category的hashcode()和equal方法。
2. 我们使用set是没有问题的,原因就是String中本身就实现了自己的hashcode()和equal方法。
3. 在这里,我们只能自己去写
4. 操作:去Pojo/Category实体类中,快捷键control + enter

5. 最后的效果:

增加功能的步骤:

  1. 新建文件controller,service(接口+实现)
    1. 每个文件的依赖对象
      1. controller依赖于:service接口
      2. service依赖于:mapper接口
  2. 【controller】在controller方法中填写最上层的操作流程,空下需要调用service的部分
  3. 【service】在service方法中填写该层的操作流程,空下需要调用mapper的部分
  4. 【dao/mapper接口】就是一个接口,声明了就行了,具体的内容在resource\mappers中xml
  5. 【resource\mappers xml】就是写sql语句,当然要符合xml的语法的
  6. 返回补全我们空下的内容

举例说明:

注:注意我在图中标出的红框配置,一点不能错

1.CategoryManagerController


2.CategoryServiceImpl


3.ICategoryService


4.dao/ProductMapper


5.Sources_mappers_CategoryMapper