项目经验:
1. 通用 servlet 设计
只定义一个 Userservlet
重写doget和dopost
例如添加用户的时候
以前: /store/addUser
现在: /store/user?method=add
修改用户的时候
以前: /store/updateUser
现在: /store/user?method=update
在 Userservlet 中 doget 方法中
String m=request.getParameter("method");
if("add".equals(m)){
add(HttpServletRequest,HttpServletResponse)
}else if("update".equals(m)){
update(HttpServletRequest,HttpServletResponse)
}else if(){
}
我们可以直接重写 service 方法即可,在 service 方法中写上面的判断代码即可
BaseServlet extends HttpServlet
其他的 servlet 继承 BaseServlet
在 baseservlet 中重写 service 方法
1. 获取请求的方法
2. 找到相应的子类 父类中的 this 代表的是子类
Class clazz=this.getClass()
3. 子类调用方法
通过方法名称 获取一个指定的方法
Method m=clazz.getMethod(方法名,HttpServletRequest.class,HttpServletResponse.class)
方法执行
m.invoke(this,HttpServletRequest,HttpServletResponse);
以前在 servlet 中
请求转发 request.getRequestDispatcher().forward()
继续完善我们 baseservlet 中 service
在第3步,方法执行返回值,
现在让所有的方法都返回一个字符串
字符串代表的是请求转发的路径
若该方法不转发只需要返回一个 null
String s=(String)m.invoke(this,HttpServletRequest,HttpServletResponse)
if(s!=null){
request.getRequestDispatcher(s).forward(request, response);
}
2. 用户注册
步骤实现:
1. 在 index.jsp 上点击 注册页面 跳转到 register.jsp
2. 点击注册
<a href="${pageContext.request.contextPath }/user?method=registUI">注册</a>
3. 在userservlet中编写一个 registUI 方法
请求转发到 register.jsp 即可
完成注册:
1. regist
封装数据
设置id
user.setUid(UUIDUtils.getId());
设置state
private Integer state=0; // 激活状态 1:激活 0:未激活
设置code
user.setCode(UUIDUtils.getCode());
请求转发 /jsp/msg.jsp
return "/jsp/msg.jsp";
2. userservice中的service
调用dao
发送激活邮件
3. userdao dao 添加一条数据
注意: 封装数据的时候报了一个错误
是因为 字符串装成时间类型的是出现错误
BeanUtils 不支持字符串装成时间
解决方案:
自定义转化器
1. 编写一个类 实现 Conventer接口
2. 实现方法
convert(转换成的类型,前台页面传入的字符串)
3. 注册转化器 在封装数据之前注册
ConvertUtils.register(new MyConventer(), Date.class);
3. 发送邮件的协议:smtp
接收邮件的协议:pop/pop3 imap
一般报java.lang.NullPointerException的原因有以下几种:
·字符串变量未初始化;
·接口类型的对象没有用具体的类初始化,比如:
List lt; 会报错
List lt = new ArrayList(); 则不会报错了
例如:
List<House> hList = new ArrayList<House>();
hList = houseService.select(name);
1.类没有初始化,例如定义了个String,List,Map 等对象没有初始化就直接使用,肯定会出空指针错误,正确初始化如下:
String str="";
List list = new ArrayList();
Map map = new HashMap();
在daoimpl的操作中:
update的操作都不需要(insert,delete)返回值
query的操作都需要返回值(select)
如何去除字符串中的符号:
直接使用空字符串替换就可以了
String b = "abcabcabc";
b=b.replace("b","");
ConvertUtils.register注册转换器
例如:
ConvertUtils.register(new DateLocaleConverter(), Date.class);
意思是所以需要转成Date类型的数据都要通过DateLocaleConverter这个转换器的处理。
如何处理date数据类型:
可以直接使用java的SimpleDateFormat类将字符串格式化为日期
例:
前台页面传入的字符串 birthdate
String dateInfo=request.getParameter("birthday");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); //此处引号内的是你需要的日期格式
Date date = null;
try {
date = format.parse(dateInfo);
} catch (ParseException e) {
e.printStackTrace();
}
date类型如何相加减:
两个日期转化为毫秒相减,相减后的毫秒转化为天数(因为日期-日期=天数)
例:
Date newDate=null;
Date oldDate=null;
前台页面传入的两个日期字符串,经过日期格式化后:
newDate=format.parse(dateInfo);
oldDate=format.parse(dateInfo1);
然后把这两个日期转化成毫秒数:
long time1=newDate.getTime();
long time2=oldDate.getTime();
再把他们相减的结果转化为天数:
long days=(time2-time1)/(24*60*60*1000);
long型数据和double型数据类型相乘,结果是double型的,因为低精度和高精度相乘结果是高精度的.
当需要进行多表联合查询的时候,可以先把这个多表查询分为多个单表查询,然后再把这些单表组合到一起:
例:
业务需求是:我是房主我需要查询到我的房子的详细订单
1.先查询到我拥有哪些房屋
SELECT house.hid from house WHERE house.uid=1; -- 我是房主这些是我的房子 1.9.10.11 1-->`user`.uid
2.我的这些房屋的详细订单
SELECT orders.* FROM orders WHERE orders.hid=10; -- 我拿我的房子的hid去找订单中找详细信息 10-->house.hid
3.把它们组合到一起
SELECT distinct o.*,u.uid as own from house h JOIN orders o ON o.hid=h.hid
JOIN `user` u on h.uid=u.uid;
注意:
如果很多表都是通过一个中间进行关联的话,要把这个中间表写在 from 后的第一个表名处
而且一般把多个单表组合成一个多表联合查询时大都是倒着写表关联,也就是把先前的步骤倒着写.
如果多表查询出现重复的数据可以使用distinct去除重复的记录:
用法: SELECT DISTINCT 列名称 FROM 表名称
页面中的跳转路径一定要写成绝对路径
关于页面中的url:
关于查询功能的界面的url全部写成:
例:
<a href="${pageContext.request.contextPath }/order?method=select&uid=${user.uid}"></a>
只要是涉及添加文字,数字等,添加东西的界面的url全部写成:
例:
<a href="${pageContext.request.contextPath }/static/html/userCenter_successOrders.jsp"></a>
SELECT h.hid,u.uid FROM house h JOIN `user` u ON
h.uid=u.uid; -- 1.拿到用户的id去house表里面去找他是否拥有房屋(hid)
SELECT o.* FROM orders o JOIN house h ON
o.hid=h.hid WHERE o.state=1;
-- 2.拿到房屋的id 去order表里面去找state=1的订单
SELECT orders.* FROM house JOIN orders ON orders.hid=house.hid
JOIN `user` ON house.uid=`user`.uid WHERE orders.state=1;
两条不同的sql语句如何一起执行:
使用: union (all,可省略)
例:
SELECT DISTINCT orders.* FROM house JOIN orders ON orders.hid=house.hid
JOIN `user` ON house.uid=3 WHERE orders.state=1
union
SELECT DISTINCT orders.* FROM orders JOIN `user` ON
orders.uid=3 WHERE orders.state=1;
-- 注意:
使用时union (all)时不能使用order by 语句
使用 UNION 运算符组合多个结果
UNION 运算符使您得以将两个或多个 SELECT 语句的结果组合成一个结果集。
使用 UNION 组合的结果集都必须具有相同的结构。而且它们的列数必须相同,
并且相应的结果集列的数据类型必须兼容(相同).
Math.ceil()函数,返回大于或者等于指定表达式的最小整数
例: Math.ceil(3.002000158)=4;
如果是JS的话,直接这样:
var totalPages = Math.ceil(opts.totalCounts / opts.pageSize);
如果是Java的话,还要强转一下:
int a = (int)Math.ceil(1.002);
文件上传(fileUpload):
浏览器端要求:
post请求
input type="file"
表单的 enctype="multipart/form-data"
服务器要求(fileUpload):
如何再使用request.getParameterxxx()获取的参数全部为空
使用步骤:
导入jar包:
commons-fileupload-1.3.3.jar
commons-io-2.5.jar
创建一个磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
创建一个核心文件上传对象 ServletUpLoad
ServletFileUpload upload = new ServletFileUpload(factory);
上传对象调用方法解析请求 获取一个List<FileItem>
List<FileItem> list = upload.parseRequest(request);
遍历list获取每一个文件项
isFormField():判断是否是普通上传组件
true:普通上传组件
false:文件上传组件
getFieldName():获取表单子标签的 name 属性值
若是普通的上传组件
getString("utf-8"):获取用户的输入值(并设置编码方式)
若是文件上传组件
getName():获取上传文件的名称
getInputStream():获取上传文件流
java中的equals和contains的区别:
equals是判断字符串的是不是相等,
例如:"abc".equals("abc"),返回结果是Boolean类型的true
"abc".equals("ab")返回结果是Boolean类型的false
contains是包含的意思,
例如:"abc".contains("a"),返回结果是Boolean类型的true
"abc".contains("d"),返回结果是Boolean类型的false.
contains包含包括,"abc".contains("abcd")是返回的false
endsWith(String suffix):
该方法返回一个true,如果参数表示的字符序列是由该对象表示的字符序列的后缀,否则返回false.
一对多:在一方编写集合(例:一个用户有多个订单)
// Hibernate框架默认的集合是set集合,集合都必须初始化
private Set<Linkman> linkmans = new HashSet<Linkman>();
在多方编写一个对象(例:一个订单属于一个用户)
// 编写一个对象,不要自己new
private Customer customer;
坐上传功能时表单具有要求:
method使用post,因为get具有上传大小限制.form表单要加入 enctype="multipart/form-data" 的属性.
同时还要写上传的 <input type="file" name="upload"/>选择框
如何解决maven自动化部署时默认部署到tomcat6下,但是我们使用的jdk的版本和tomcat6不兼容,需要改为tomcat7:
1.在pom.xml中写入:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</build>
2.在run as 中 设置为tomcat7:run即可 不要写成 tomcat:run(这是tomcat6的发布方法),他们的默认端口都是8080
如果 Web 应用程序采用了经典的三层分层结构的话:
最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释
el表达式中的forEach中的varStatus:
varStatus: 显示循环状态的变量,index:从0开始; 显示当前迭代的索引值
例:
<c:forEach items="${itemList }" var="item" varStatus="status">
<tr>
<!-- name属性名称要等于vo中的接收的属性名 -->
<td>
<input type="checkbox" name="ids" value="${item.id }"/>
<input type="hidden" name="itemsList[${status.index }].id" value="${item.id }">
</td>
<td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"></td>
<td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"></td>
<td><input type="text" name="itemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"></td>
<td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
springMvc中建议使用model
例:
String idStr = request.getParameter("id");
Items items = itemsService.findItemsById(Integer.parseInt(idStr));
// Model模型:模型中放入了返回给页面的数据
// model底层其实就是用的request域来传递数据,但是对request域进行了扩展
model.addAttribute("item", items);
// 如果springMvc方法返回一个简单的string字符串,那么springMvc就会认为这个字符串就是页面的名称
return "editItem";
请求转发:浏览器中url不发生改变,request域中的数据可以带到转发后的方法中
springMvc中请求转发:返回的字符串以forward:开头的都是请求转发
建议所有的路径都是用绝对路径:
例:
return "forward:/items/itemEdit.action";
绝对路径从项目名后面开始算.
例:http://localhost:8080/ssm-01/items/list.action 项目名为:ssm-01
重定向;浏览器中url发生改变,request域中的数据不可以带到重定向后的方法中
在springMvc中凡是以redirect:字符串开头的都为重定向
例:
return "redirect:/items/itemEdit.action";
@RequestBody
application/json 格式的数据必须使用@RequestBody来处理
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
restful风格编程:
通过注解@PathVariable可以接收url中传入的参数
例:
@RequestMapping("/viewItems/{id}")
public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
ItemsCustom itemsCustom = itemsService.findItemsById(id);
注意:
@RequestMapping("/viewItems/{id}")中接收参数使用大括号中加上变量名称,
@PathVariable中的变量名称要和@RequestMapping中的变量名称相同
例:
model.addAttribute("id",items.getId);
return "redirect:itemEdit"; 这样的页面是:localhost:8080/xxx/items/itemEdit?id=1
可以改写为:
return "redirect:itemEdit/"+items.getId; 这样的页面是:localhost:8080/xxx/items/itemEdit/1
Spring是什么:Spring是一个库,它的功能是提供了一个软件框架,这个框架目的是使软件之间的逻辑更加清晰,配置更灵活,
实现这个目的的手段使用AOP和IoC,而AOP和IoC是一种思想.
AOP在Java里是利用反射机制实现
window环境下杀死进程
首先查找到占用8080端口的进程号PID是多少
netstat -ano | findstr 8080
kill掉这个进程
taskkill /f /pid xxx
1. 通用 servlet 设计
只定义一个 Userservlet
重写doget和dopost
例如添加用户的时候
以前: /store/addUser
现在: /store/user?method=add
修改用户的时候
以前: /store/updateUser
现在: /store/user?method=update
在 Userservlet 中 doget 方法中
String m=request.getParameter("method");
if("add".equals(m)){
add(HttpServletRequest,HttpServletResponse)
}else if("update".equals(m)){
update(HttpServletRequest,HttpServletResponse)
}else if(){
}
我们可以直接重写 service 方法即可,在 service 方法中写上面的判断代码即可
BaseServlet extends HttpServlet
其他的 servlet 继承 BaseServlet
在 baseservlet 中重写 service 方法
1. 获取请求的方法
2. 找到相应的子类 父类中的 this 代表的是子类
Class clazz=this.getClass()
3. 子类调用方法
通过方法名称 获取一个指定的方法
Method m=clazz.getMethod(方法名,HttpServletRequest.class,HttpServletResponse.class)
方法执行
m.invoke(this,HttpServletRequest,HttpServletResponse);
以前在 servlet 中
请求转发 request.getRequestDispatcher().forward()
继续完善我们 baseservlet 中 service
在第3步,方法执行返回值,
现在让所有的方法都返回一个字符串
字符串代表的是请求转发的路径
若该方法不转发只需要返回一个 null
String s=(String)m.invoke(this,HttpServletRequest,HttpServletResponse)
if(s!=null){
request.getRequestDispatcher(s).forward(request, response);
}
2. 用户注册
步骤实现:
1. 在 index.jsp 上点击 注册页面 跳转到 register.jsp
2. 点击注册
<a href="${pageContext.request.contextPath }/user?method=registUI">注册</a>
3. 在userservlet中编写一个 registUI 方法
请求转发到 register.jsp 即可
完成注册:
1. regist
封装数据
设置id
user.setUid(UUIDUtils.getId());
设置state
private Integer state=0; // 激活状态 1:激活 0:未激活
设置code
user.setCode(UUIDUtils.getCode());
请求转发 /jsp/msg.jsp
return "/jsp/msg.jsp";
2. userservice中的service
调用dao
发送激活邮件
3. userdao dao 添加一条数据
注意: 封装数据的时候报了一个错误
是因为 字符串装成时间类型的是出现错误
BeanUtils 不支持字符串装成时间
解决方案:
自定义转化器
1. 编写一个类 实现 Conventer接口
2. 实现方法
convert(转换成的类型,前台页面传入的字符串)
3. 注册转化器 在封装数据之前注册
ConvertUtils.register(new MyConventer(), Date.class);
3. 发送邮件的协议:smtp
接收邮件的协议:pop/pop3 imap
一般报java.lang.NullPointerException的原因有以下几种:
·字符串变量未初始化;
·接口类型的对象没有用具体的类初始化,比如:
List lt; 会报错
List lt = new ArrayList(); 则不会报错了
例如:
List<House> hList = new ArrayList<House>();
hList = houseService.select(name);
1.类没有初始化,例如定义了个String,List,Map 等对象没有初始化就直接使用,肯定会出空指针错误,正确初始化如下:
String str="";
List list = new ArrayList();
Map map = new HashMap();
在daoimpl的操作中:
update的操作都不需要(insert,delete)返回值
query的操作都需要返回值(select)
如何去除字符串中的符号:
直接使用空字符串替换就可以了
String b = "abcabcabc";
b=b.replace("b","");
ConvertUtils.register注册转换器
例如:
ConvertUtils.register(new DateLocaleConverter(), Date.class);
意思是所以需要转成Date类型的数据都要通过DateLocaleConverter这个转换器的处理。
如何处理date数据类型:
可以直接使用java的SimpleDateFormat类将字符串格式化为日期
例:
前台页面传入的字符串 birthdate
String dateInfo=request.getParameter("birthday");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); //此处引号内的是你需要的日期格式
Date date = null;
try {
date = format.parse(dateInfo);
} catch (ParseException e) {
e.printStackTrace();
}
date类型如何相加减:
两个日期转化为毫秒相减,相减后的毫秒转化为天数(因为日期-日期=天数)
例:
Date newDate=null;
Date oldDate=null;
前台页面传入的两个日期字符串,经过日期格式化后:
newDate=format.parse(dateInfo);
oldDate=format.parse(dateInfo1);
然后把这两个日期转化成毫秒数:
long time1=newDate.getTime();
long time2=oldDate.getTime();
再把他们相减的结果转化为天数:
long days=(time2-time1)/(24*60*60*1000);
long型数据和double型数据类型相乘,结果是double型的,因为低精度和高精度相乘结果是高精度的.
当需要进行多表联合查询的时候,可以先把这个多表查询分为多个单表查询,然后再把这些单表组合到一起:
例:
业务需求是:我是房主我需要查询到我的房子的详细订单
1.先查询到我拥有哪些房屋
SELECT house.hid from house WHERE house.uid=1; -- 我是房主这些是我的房子 1.9.10.11 1-->`user`.uid
2.我的这些房屋的详细订单
SELECT orders.* FROM orders WHERE orders.hid=10; -- 我拿我的房子的hid去找订单中找详细信息 10-->house.hid
3.把它们组合到一起
SELECT distinct o.*,u.uid as own from house h JOIN orders o ON o.hid=h.hid
JOIN `user` u on h.uid=u.uid;
注意:
如果很多表都是通过一个中间进行关联的话,要把这个中间表写在 from 后的第一个表名处
而且一般把多个单表组合成一个多表联合查询时大都是倒着写表关联,也就是把先前的步骤倒着写.
如果多表查询出现重复的数据可以使用distinct去除重复的记录:
用法: SELECT DISTINCT 列名称 FROM 表名称
页面中的跳转路径一定要写成绝对路径
关于页面中的url:
关于查询功能的界面的url全部写成:
例:
<a href="${pageContext.request.contextPath }/order?method=select&uid=${user.uid}"></a>
只要是涉及添加文字,数字等,添加东西的界面的url全部写成:
例:
<a href="${pageContext.request.contextPath }/static/html/userCenter_successOrders.jsp"></a>
SELECT h.hid,u.uid FROM house h JOIN `user` u ON
h.uid=u.uid; -- 1.拿到用户的id去house表里面去找他是否拥有房屋(hid)
SELECT o.* FROM orders o JOIN house h ON
o.hid=h.hid WHERE o.state=1;
-- 2.拿到房屋的id 去order表里面去找state=1的订单
SELECT orders.* FROM house JOIN orders ON orders.hid=house.hid
JOIN `user` ON house.uid=`user`.uid WHERE orders.state=1;
两条不同的sql语句如何一起执行:
使用: union (all,可省略)
例:
SELECT DISTINCT orders.* FROM house JOIN orders ON orders.hid=house.hid
JOIN `user` ON house.uid=3 WHERE orders.state=1
union
SELECT DISTINCT orders.* FROM orders JOIN `user` ON
orders.uid=3 WHERE orders.state=1;
-- 注意:
使用时union (all)时不能使用order by 语句
使用 UNION 运算符组合多个结果
UNION 运算符使您得以将两个或多个 SELECT 语句的结果组合成一个结果集。
使用 UNION 组合的结果集都必须具有相同的结构。而且它们的列数必须相同,
并且相应的结果集列的数据类型必须兼容(相同).
Math.ceil()函数,返回大于或者等于指定表达式的最小整数
例: Math.ceil(3.002000158)=4;
如果是JS的话,直接这样:
var totalPages = Math.ceil(opts.totalCounts / opts.pageSize);
如果是Java的话,还要强转一下:
int a = (int)Math.ceil(1.002);
文件上传(fileUpload):
浏览器端要求:
post请求
input type="file"
表单的 enctype="multipart/form-data"
服务器要求(fileUpload):
如何再使用request.getParameterxxx()获取的参数全部为空
使用步骤:
导入jar包:
commons-fileupload-1.3.3.jar
commons-io-2.5.jar
创建一个磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
创建一个核心文件上传对象 ServletUpLoad
ServletFileUpload upload = new ServletFileUpload(factory);
上传对象调用方法解析请求 获取一个List<FileItem>
List<FileItem> list = upload.parseRequest(request);
遍历list获取每一个文件项
isFormField():判断是否是普通上传组件
true:普通上传组件
false:文件上传组件
getFieldName():获取表单子标签的 name 属性值
若是普通的上传组件
getString("utf-8"):获取用户的输入值(并设置编码方式)
若是文件上传组件
getName():获取上传文件的名称
getInputStream():获取上传文件流
java中的equals和contains的区别:
equals是判断字符串的是不是相等,
例如:"abc".equals("abc"),返回结果是Boolean类型的true
"abc".equals("ab")返回结果是Boolean类型的false
contains是包含的意思,
例如:"abc".contains("a"),返回结果是Boolean类型的true
"abc".contains("d"),返回结果是Boolean类型的false.
contains包含包括,"abc".contains("abcd")是返回的false
endsWith(String suffix):
该方法返回一个true,如果参数表示的字符序列是由该对象表示的字符序列的后缀,否则返回false.
一对多:在一方编写集合(例:一个用户有多个订单)
// Hibernate框架默认的集合是set集合,集合都必须初始化
private Set<Linkman> linkmans = new HashSet<Linkman>();
在多方编写一个对象(例:一个订单属于一个用户)
// 编写一个对象,不要自己new
private Customer customer;
坐上传功能时表单具有要求:
method使用post,因为get具有上传大小限制.form表单要加入 enctype="multipart/form-data" 的属性.
同时还要写上传的 <input type="file" name="upload"/>选择框
如何解决maven自动化部署时默认部署到tomcat6下,但是我们使用的jdk的版本和tomcat6不兼容,需要改为tomcat7:
1.在pom.xml中写入:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</build>
2.在run as 中 设置为tomcat7:run即可 不要写成 tomcat:run(这是tomcat6的发布方法),他们的默认端口都是8080
如果 Web 应用程序采用了经典的三层分层结构的话:
最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释
el表达式中的forEach中的varStatus:
varStatus: 显示循环状态的变量,index:从0开始; 显示当前迭代的索引值
例:
<c:forEach items="${itemList }" var="item" varStatus="status">
<tr>
<!-- name属性名称要等于vo中的接收的属性名 -->
<td>
<input type="checkbox" name="ids" value="${item.id }"/>
<input type="hidden" name="itemsList[${status.index }].id" value="${item.id }">
</td>
<td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"></td>
<td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"></td>
<td><input type="text" name="itemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"></td>
<td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
springMvc中建议使用model
例:
String idStr = request.getParameter("id");
Items items = itemsService.findItemsById(Integer.parseInt(idStr));
// Model模型:模型中放入了返回给页面的数据
// model底层其实就是用的request域来传递数据,但是对request域进行了扩展
model.addAttribute("item", items);
// 如果springMvc方法返回一个简单的string字符串,那么springMvc就会认为这个字符串就是页面的名称
return "editItem";
请求转发:浏览器中url不发生改变,request域中的数据可以带到转发后的方法中
springMvc中请求转发:返回的字符串以forward:开头的都是请求转发
建议所有的路径都是用绝对路径:
例:
return "forward:/items/itemEdit.action";
绝对路径从项目名后面开始算.
例:http://localhost:8080/ssm-01/items/list.action 项目名为:ssm-01
重定向;浏览器中url发生改变,request域中的数据不可以带到重定向后的方法中
在springMvc中凡是以redirect:字符串开头的都为重定向
例:
return "redirect:/items/itemEdit.action";
@RequestBody
application/json 格式的数据必须使用@RequestBody来处理
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
restful风格编程:
通过注解@PathVariable可以接收url中传入的参数
例:
@RequestMapping("/viewItems/{id}")
public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
ItemsCustom itemsCustom = itemsService.findItemsById(id);
注意:
@RequestMapping("/viewItems/{id}")中接收参数使用大括号中加上变量名称,
@PathVariable中的变量名称要和@RequestMapping中的变量名称相同
例:
model.addAttribute("id",items.getId);
return "redirect:itemEdit"; 这样的页面是:localhost:8080/xxx/items/itemEdit?id=1
可以改写为:
return "redirect:itemEdit/"+items.getId; 这样的页面是:localhost:8080/xxx/items/itemEdit/1
Spring是什么:Spring是一个库,它的功能是提供了一个软件框架,这个框架目的是使软件之间的逻辑更加清晰,配置更灵活,
实现这个目的的手段使用AOP和IoC,而AOP和IoC是一种思想.
AOP在Java里是利用反射机制实现
window环境下杀死进程
首先查找到占用8080端口的进程号PID是多少
netstat -ano | findstr 8080
kill掉这个进程
taskkill /f /pid xxx