1 重点
Ø 掌握使用struts2实现文件上传功能
Ø 能够使用FastJSON将对象转换为JSON
Ø 能够使用JSON插件完成Ajax开发
Ø 掌握使用struts2基于注解方式实现登录、商品展示案例
2 第一节课
2.1 struts2如何实现文件上传
注意事项:
Ø 表单提交方式method=”post”
Ø 表单中必须有一个<inputtype=”file”>组件
Ø 表单中必须设置enctype=”multipart/form-data”
struts2使用fileUpload的拦截器来实现文件上传。
2.2 文件上传快速入门(掌握)
Ø 创建upload.jsp页面
<formaction="${pageContext.request.contextPath}/upload"method="post"enctype="multipart/form-data">
<inputname="img"type="file">
<inputtype="submit"value="提交">
</form>
Ø 编写UploadAction.java
注意:如果<input name=”cImg”type=”file” />,则应该在Action中提供setCImg方法。要将首字母大写。
public class UploadAction extends ActionSupport {
// 名称与表单上<input>的名称保持一致
private Fileimg; // 上传的文件
private StringimgFileName; //上传的文件名
private StringimgContentType; // 上传的文件类型
@Override
public String execute()throws Exception {
String uploadPath =ServletActionContext.getServletContext().getRealPath("/upload");
File dest = new File(uploadPath,imgFileName);
// 将文件拷贝到upload目录
FileUtils.copyFile(img,dest);
return NONE;
}
// 生成set方法
public void setImg(File img) {
this.img =img;
}
public void setImgFileName(StringimgFileName) {
this.imgFileName =imgFileName;
}
public void setImgContentType(String imgContentType) {
this.imgContentType =imgContentType;
}
}
Ø 配置struts.xml
<packagename="default"extends="struts-default"namespace="/">
<actionname="upload"class="com.itheima.action.UploadAction"></action>
</package>
测试说明:
此时上传的文件是存放在tomcat目录下的项目根目录的upload文件夹中的, 而不是工作空间下.
1.1 配置input视图查看文件上传问题
Ø 编写error.jsp页面,用来显示Action的input视图
<%@ page language="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglibprefix="s"uri="/struts-tags"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>错误</title>
</head>
<body>
<s:actionerror/>
<s:fielderror/>
</body>
</html>
Ø 在struts.xml文件中配置对应的result
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEstruts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode "value="true"></constant>
<packagename="default"extends="struts-default"namespace="/">
<global-results>
<resultname="input">/error.jsp</result>
</global-results>
<actionname="upload"class="com.itheima.action.UploadAction"></action>
</package>
</struts>
struts.devMode配置可以让struts2报错的时候显示更加详细的错误信息,这个配置在struts2的core下的org.apache.struts2的default.properties.
如果上传文件的大小超过限制,则会转发到该视图。
问题:上传超过限制文件大小时报异常,页面显示为无法访问此网站(以下为chrome截图)
这是tomcat7高版本的一个bug,请下载7.0.39版本的tomcat。
http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.39/bin/apache-tomcat-7.0.39.zip
1.1 设置文件上传配置
1.1.1 设置文件上传最大的大小(掌握)
<constantname="struts.multipart.maxSize"value="209715200"></constant>
它是描述文件上传时允许的最大值(是一次请求的总大小,而不是一个文件的大小)如果下面的param中的maximum的大小大于此时的全局时取小的为准.
<packagename="default"extends="struts-default"namespace="/">
<global-results>
<resultname="input">/error.jsp</result>
</global-results>
<actionname="upload"class="com.itheima.action.UploadAction">
<interceptor-refname="fileUpload">
<paramname="maximumSize">20971520</param>
<paramname="allowedExtensions">zip,png,gif,jpg,jpeg</param>
</interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>
</package>
我们还可以查看FileuploadInterceptor在struts.xml中配置指定上传的相关限制::
1.1.1 上传多个文件
Ø 编写JSP页面
<formaction="${pageContext.request.contextPath}/upload1"method="post"enctype="multipart/form-data">
<inputname="img"type="file"><br/>
<inputname="img"type="file"><br/>
<inputname="img"type="file"><br/>
<inputtype="submit"value="提交">
</form>
Ø 编写Action
public class UploadAction extends ActionSupport {
// 名称与表单上<input>的名称保持一致
private File[] img; // 上传的文件
private String[] imgFileName; // 上传的文件名
private String[] imgContentType; // 上传的文件类型
@Override
public String execute()throws Exception {
String uploadPath =ServletActionContext.getServletContext().getRealPath("/upload");
for(inti = 0; i < img.length; ++i) {
File dest = new File(uploadPath,imgFileName[i]);
// 将文件拷贝到upload目录
FileUtils.copyFile(img[i],dest);
}
return NONE;
}
// 生成set方法
public void setImg(File[] img) {
this.img =img;
}
public void setImgFileName(String[] imgFileName) {
this.imgFileName =imgFileName;
}
public void setImgContentType(String[] imgContentType) {
this.imgContentType =imgContentType;
}
}
如果我们上传时,允许上传多个文件如何操作?
Action如何处理?
方式一写成数组形式:
方式二:也可以使用List<File> List<String>来控制属性
在方法中
1 第二节课
1.1 JSON数据格式介绍
JSON是一种简单的数据格式。
1.1.1 JSON结构(掌握)
json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构。
1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为对象.key 获取属性值,这个属性值的类型可以是数字、字符串、数组、对象几种。
2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。
可以下载JsonView工具 , 可视化的查看Json的层次结构
Ø Javascript的对象
{name: ‘tomcat’, age:20}
Ø 数组
[‘tomcat’, ‘20’]
Ø 嵌套
{
"employees":[
{
"firstName":"Bill",
"lastName":"Gates"
},
{
"firstName":"George",
"lastName":"Bush"
},
{
"firstName":"Thomas",
"lastName":"Carter"
}
]
}
JSON View
Java中json工具介绍【重点】
有两种:FastJSON以及Jackson.
1.1 FastJSON简单使用(掌握)
将服务器端的java格式的对象转成Json返回给浏览器端.
Ø 导入fastJSONjar包
Ø 编写测试用的Java实体类
public class User {
private Integerid;
private Stringname;
//通过注解对Date类型进行格式化输出
@JSONField(format="yyyy-MM-ddHH:mm:ss")
private Datebirthday;
private Stringgender;
public Integer getId() {
returnid;
}
public void setId(Integer id) {
this.id =id;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public Date getBirthday() {
returnbirthday;
}
public void setBirthday(Date birthday) {
this.birthday =birthday;
}
public String getGender() {
returngender;
}
public void setGender(String gender) {
this.gender =gender;
}
}
Ø 将对象转化为JSON
@Test
public void test01() {
User user = new User();
user.setBirthday(new Date());
user.setGender("男");
user.setName("蠢爸爸");
user.setId(1);
// 对象转为json
String jsonString = JSONObject.toJSONString(user);
System.out.println(jsonString);
}
Ø 将数组转换为JSON
@Test
public void test02() {
User user1 = new User();
user1.setBirthday(new Date());
user1.setGender("男");
user1.setName("蠢爸爸");
user1.setId(1);
User user2 = new User();
user2.setBirthday(new Date());
user2.setGender("女");
user2.setName("笨鸡蛋");
user2.setId(2);
ArrayList<User> arrayList =newArrayList<User>();
arrayList.add(user1);
arrayList.add(user2);
String jsonString1 = JSONObject.toJSONString(arrayList);
String jsonString2 = JSONArray.toJSONString(arrayList);
System.out.println(jsonString1);
System.out.println(jsonString2);
}
Ø 过滤某些属性
当某些属性不需要生成在json串中的设置:
@Test
public void test03() {
User user1 = new User();
user1.setBirthday(new Date());
user1.setGender("男");
user1.setName("蠢爸爸");
user1.setId(1);
ArrayList<User> arrayList =newArrayList<User>();
arrayList.add(user1);
PropertyFilter propertyFilter =new PropertyFilter() {
@Override
public boolean apply(Object arg0, Stringname, Object arg2) {
if(name.equals("id"))
returnfalse; // id属性不输出到JSON串中
returntrue;
}
};
// 过滤id属性
String jsonString = JSONObject.toJSONString(arrayList,propertyFilter);
System.out.println(jsonString);
}
1.1 jackson简单使用
Ø 导入jackson jar包
Ø 创建实体类
@JsonFilter("userFilter")// 使用Filter动态过滤属性时添加
@JsonIgnoreProperties({"id","birthday"})// 过略多个属性
public class User {
@JsonIgnore //过滤单个属性
private Integerid;
private Stringname;
private Datebirthday;
private Stringgender;
public Integer getId() {
returnid;
}
public void setId(Integer id) {
this.id =id;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public Date getBirthday() {
returnbirthday;
}
public void setBirthday(Date birthday) {
this.birthday =birthday;
}
public String getGender() {
returngender;
}
public void setGender(String gender) {
this.gender =gender;
}
}
Ø 将对象转换为JSON
@Test
public void test01() throws JsonGenerationException,JsonMappingException, IOException {
User user = new User();
user.setBirthday(new Date());
user.setGender("男");
user.setName("蠢爸爸");
user.setId(1);
// 对象转为json
ObjectMapper objectMapper =new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
System.out.println(json);
}
Ø 将数组转换为JSON
@Test
public void test02() throws JsonGenerationException,JsonMappingException, IOException {
User user1 = new User();
user1.setBirthday(new Date());
user1.setGender("男");
user1.setName("蠢爸爸");
user1.setId(1);
User user2 = new User();
user2.setBirthday(new Date());
user2.setGender("女");
user2.setName("笨鸡蛋");
user2.setId(2);
ArrayList<User> arrayList =newArrayList<User>();
arrayList.add(user1);
arrayList.add(user2);
ObjectMapper objectMapper =new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
String json = objectMapper.writeValueAsString(arrayList);
System.out.println(json);
}
Ø 动态过滤对象属性
过滤属性() ,
@JsonIgnoreProperties过滤掉所有的该类对象的多个属性 , 在不同的功能需要过滤不同的属性的时候就不是很实用了
@JsonIgnore过滤掉单个属性.也是所有功能都会过滤.
在不同的功能需要过滤不同的属性的时候 ,我们通过编码方案实现
需要在类上添加一个注解
@Test
public void test03() throws JsonGenerationException,JsonMappingException, IOException {
User user1 = new User();
user1.setBirthday(new Date());
user1.setGender("男");
user1.setName("蠢爸爸");
user1.setId(1);
// Jackson动态过滤JSON属性
ObjectMapperobjectMapper =new ObjectMapper();
// 初始化过滤器
SimpleFilterProvider simpleFilterProvider =new SimpleFilterProvider();
simpleFilterProvider.addFilter("userFilter",SimpleBeanPropertyFilter.serializeAllExcept("id"));
objectMapper.setFilters(simpleFilterProvider);
String json = objectMapper.writeValueAsString(user1);
System.out.println(json);
}
注意:
如果此时没有在User类中写@JsonFilter("userFilter")// 使用Filter动态过滤属性时添加的话,是起不到过滤效果的.
如果再User类上声明了动态过滤属性时 , 运行没有初始化过滤器的测试方法的时候会报错啊. 如果需要用到该类的每个功能都要初始化过滤器的话那不是很麻烦吗?
1 第三节课
Strtus2框架如果处理ajax请求【重点】
有两种方式:
第一种:使用response直接将数据相应到浏览器端.
第二种; 使用Struts2框架提供的json插件来完成ajax操作.
补充:
在xml中引用其他的xml简化内容:
1.1 使用response响应数据(掌握)
可以使用HttpServletResponse响应数据
在struts2框架中可以获取HttpServletResponse对象,就可以通过response来完成将数据(json)响应到浏览器过程
1.1.1 浏览器端
需要使用onblure失去焦点事务来处理文本框,向服务器发送ajax请求(jquery完成)
Ø 准备环境
导入JAR包(这里使用Jackson转换JSON)
导入jquery
Ø 编写JSP
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPEhtml PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<scripttype="text/javascript"src="jquery-1.11.3.js"></script>
<title>登录</title>
</head>
<body>
<table>
<tr>
<td>用户名</td>
<td>
<inputname="username"onblur="checkUserName()"/>
<spanid="msg"></span>
</td>
</tr>
<tr>
<td>密码</td>
<td><inputname="password"type="password"/></td>
</tr>
</table>
<scripttype="text/javascript">
function checkUserName() {
$.post('${pageContext.request.contextPath}/check',
{username: $('input[name="username"]').val()},
function(data){
console.log(data);
if(data.flag) {
$('#msg').css("color","#FF0000").text(data.message);
}
else {
$('#msg').css("color","#6CB33E").text(data.message);
}
},'json')
}
</script>
</body>
</html>
Ø 编写Result类
public class Result {
private boolean flag;
private Stringmessage;
public boolean isFlag() {
returnflag;
}
public void setFlag(booleanflag) {
this.flag =flag;
}
public String getMessage() {
returnmessage;
}
public void setMessage(String message) {
this.message =message;
}
}
Ø 编写Action
public class UserAction extends ActionSupport{
public String execute()throws Exception {
String username = ServletActionContext.getRequest().getParameter("username");
Result r = new Result();
if(username.equals("tom")) {
r.setFlag(true);
r.setMessage("该用户名已经存在");
}
else {
r.setFlag(false);
r.setMessage("用户名可用");
}
ObjectMapper objectMapper =new ObjectMapper();
String json =objectMapper.writeValueAsString(r);
HttpServletResponse response = ServletActionContext.getResponse();
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);
return NONE;
}
}
Ø 编写配置文件
<constantname="struts.devMode"value="true"></constant>
<packagename="default"extends="struts-default"namespace="/">
<actionname="check"class="com.itheima.action.UserAction"></action>
</package>
相同原理的视频中的测试流程;
1.1.1 浏览器端
需要使用onblure失去焦点事务来处理文本框,向服务器发送ajax请求(jquery完成)
1.1.1 服务器端
1.1.1 配置action:
数据响应没有问题,处理中文乱码
1.1.1 在浏览器端处理服务器响应的数据
扩展
jQuery中的$.post( url, [data], [callback], [type] ) ,异步请求: 参数: url (String) : (必需)发送请求的URL地址. data (Map) : (可选) 要发送给服务器的数据,以 Key/value 的键值对形式表示。 callback (Function) : (可选) 载入成功时回调函数(只有当Response的返回状态是success才是调用该方法)。 type (String) : (可选)官方的说明是:规定预期的服务器响应的数据类型。(xml、json、script 或 html) 该函数是简写的 Ajax 函数,等价于: $.ajax({ type: 'POST', url: url, data: data, success: success, dataType: dataType }); |
1.2 struts2框架中的json插件(掌握)
首先要导入插件包 , 在struts2的源码包里的lib中名字叫struts2-json-plugin-2.3.24.jar
我们怎样使用struts2提供的json插件?
1. 将我们自己配置文件中的<package extends=”json-default”>.
2. Action的返回视图<resultname=”” type=”json”>
因为我们配置了上面两步,那么struts2框架就会将valueStack中的栈顶元素转换成json响应到浏览器
1.1 请求显示商品信息(掌握)
1.1.1 Json插件的开发流程
Ø 导入struts-json-plugin.jar包
Ø 导入jquery
Ø 编写JSP页面
<aid="a"href="javascript:void(0)">商品列表</a>
<divid="product"></div>
<scripttype="text/javascript">
$('#a').click(function() {
if($('#product').html() =="") {
$.post('${pageContext.request.contextPath}/product',
function(data) {
console.log(data);
var html ='<tableborder="1" cellspacing="0" cellpadding="5">'
+ '<tr>'
+ '<td>编号</td>'
+ '<td>价格</td>'
+ '<td>描述</td>'
+'</tr>';
for(var i = 0; i <data.length; ++i) {
html += '<tr>'
+ '<td>' + data[i].name +'</td>'
+ '<td>' +data[i].price +'</td>'
+ '<td>' +data[i].description +'</td>'
+ '</tr>';
}
html += '</table>';
$('#product').html(html);
$('#product').show();
}, 'json');
}
else {
$('#product').html("");
}
});
</script>
Ø 编写Product实体类
public class Product {
private Stringname;
private Doubleprice;
private Stringdescription;
private DatereleaseDate;
@JSON(format="yyyy-MM-dd HH:mm", serialize=false)
public Date getReleaseDate() {
returnreleaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate =releaseDate;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public Double getPrice() {
returnprice;
}
public void setPrice(Double price) {
this.price =price;
}
public String getDescription() {
returndescription;
}
public void setDescription(String description) {
this.description =description;
}
}
Ø 编写ProductAction
public class ProductAction extends ActionSupport{
public String execute() {
List<Product> products =newArrayList<Product>();
Product p1 = new Product();
p1.setName("iphone 5");
p1.setDescription("苹果5");
p1.setPrice(1800.1);
p1.setReleaseDate(new Date());
Product p2 = new Product();
p2.setName("iphone 6");
p2.setDescription("苹果6");
p2.setPrice(2800.1);
p2.setReleaseDate(new Date());
Product p3 = new Product();
p3.setName("iphone 7");
p3.setDescription("苹果7");
p3.setPrice(4800.1);
p3.setReleaseDate(new Date());
products.add(p1);
products.add(p2);
products.add(p3);
ActionContext.getContext().getValueStack().push(products);
return SUCCESS;
}
}
Ø 编写struts.xml
<packagename="default"extends="json-default"namespace="/">
<actionname="product"class="com.itheima.action.ProductAction">
<resulttype="json"></result>
</action>
</package>
1.1. 案例---查找商品信息
1.1.2 浏览器端操作
1.1.1 服务器端
关于响应的json处理:
1. 怎样忽略属性
上面这种方案有弊端
在org.apache.struts2.json.JSONResult类中有两个属性
它们可以设置响应的数据中是否包含或不包含属性
1. 设置root
没有设置root前返回的json结构ps:[{},{}]
设置root它的根为ps后的返回的json [{},{}]
1.1.1 处理服务器响应数据到浏览器展示
1 第四节课
1.1 商品信息展示
Ø 过略掉一些其他属性
includeProperties(包含的属性) ps\[\d+\]\.releaseDate
excludeProperties(要不包含的属性)
Ø 设置root
<param name=”root”>ps</param>
Ø 扩展
可以使用@JSON注解来配置要转换的日期格式,以及忽略某些属性
1.1 注解开发快速入门(掌握)
Ø 导入JAR包
Ø 编写JSP页面
<a href="${pageContext.request.contextPath }/hello">hello world!</a>
Ø 编写Action
@Namespace("/")
@ParentPackage("struts-default")
public class HelloAction extends ActionSupport{
@Action(value="hello",results=@Result(location="/success.jsp"))
public String sayHello() {
return SUCCESS;
}
}
1.1 其他注解与注意事项(了解)
Ø @Actions:可以通过配置多个@Action来映射同一个Action
@Actions({
@Action(value="hello", results=@Result(location="/success.jsp")),
@Action(value="hello1", results=@Result(location="/success.jsp"))
})
public String sayHello() {
return SUCCESS;
}
Ø @Results注解
可以定一些@result供Action使用
@Action(results={@Result(name=””,type=””,location=””)})
@Namespace("/")
@ParentPackage("struts-default")
@Results({
@Result(location="/success.jsp")
})
public class HelloAction extends ActionSupport{
@Actions({
@Action(value="hello"),
@Action(value="hello1")
})
public String sayHello() {
return SUCCESS;
}
}
Ø 使用@InterceptorRefs(“defaultStack”)来指定使用拦截器
@Action(value="hello",interceptorRefs=@InterceptorRef("defaultStack")))
@Results
类似于全局的结果视图
问题:我们在action类中定义了注解,strtus2框架怎样识别它们?
原因:我们必须查看插件包中的配置
是在action,actions,struts,struts2这样的包下扫描注解
注意:需要将Action放在包含action、actions、struts、struts2下,同时Action类命名默认需以Action结尾。例如:包名com.itheima.action,类名UserAction/CustomerAction
1 第五节课
1.1 使用注解开发完成案例——(重点练习)
搭建环境
Ø 创建数据库与表
DROP DATABASE exam;
CREATE DATABASE exam;
USE exam;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
PASSWORD VARCHAR(20)
);
INSERT INTO USER VALUES(NULL,'tom','123');
INSERT INTO USER VALUES(NULL,'fox','456');
CREATE TABLE product(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
COUNT INT,
price DOUBLE
);
INSERT INTO product VALUES(NULL,'电视机',100,1200);
INSERT INTO product VALUES(NULL,'洗衣机',800,2200);
INSERT INTO product VALUES(NULL,'空调机',10,3200);
Ø 导入JAR包(C3P0 JAR包、MYSQL驱动JAR包、DBUtils JAR包)
Ø 编写配置文件
web.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appid="WebApp_9"version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>struts2 DEMO</display-name>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
struts.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEstruts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constantname="struts.devMode"value="true"></constant>
</struts>
c3p0.properties
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/struts2
c3p0.user=root
c3p0.password=000000
Ø 创建包结构
Ø 编写JdbcUtils工具类
public class JdbcUtils {
private static DataSource dataSource =newComboPooledDataSource();
public static DataSource getDataSource() {
returndataSource;
}
public static Connection getConnection() throws SQLException {
return (Connection)dataSource.getConnection();
}
}
1.1 注解案例——登录操作
Ø 编写login.jsp
<%@ page language="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c"uri="/struts-tags"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>登录</title>
</head>
<body>
<formaction="${pageContext.request.contextPath}/user_login"method="post">
用户名: <inputtype="text"name="username"/>
密码:<inputtype="password"name="password"/>
<inputtype="submit"value="登录">
</form>
</body>
</html>
Ø 编写User实体类
public class User {
private Integerid;
private Stringusername;
private Stringpassword;
public Integer getId() {
returnid;
}
public void setId(Integer id) {
this.id =id;
}
public String getUsername() {
returnusername;
}
public void setUsername(String username) {
this.username =username;
}
public String getPassword() {
returnpassword;
}
public void setPassword(String password) {
this.password =password;
}
}
Ø 编写UerDao
接口(UserDao)
public interface UserDao {
UserfindByUsernameAndPassword(String username, String password);
}
实现(UserDaoImpl)
public class UserDaoImpl implements UserDao{
@Override
public UserfindByUsernameAndPassword(Stringusername, String password) {
QueryRunner queryRunner =newQueryRunner(JdbcUtils.getDataSource());
try {
// 根据用户名和密码进行检索
returnqueryRunner.query("select * from user where username=? andpassword=?",
newBeanHandler<User>(User.class),
username,
password);
} catch (SQLExceptione) {
e.printStackTrace();
}
return null;
}
}
Ø 编写UserService
接口(UserService)
public interface UserService {
UserfindByUsernameAndPassword(String username, String password);
}
实现(UserServiceImpl)
public class UserServiceImpl implements UserService{
@Override
public UserfindByUsernameAndPassword(Stringusername, String password) {
UserDao userDao =new UserDaoImpl();
returnuserDao.findByUsernameAndPassword(username,password);
}
}
Ø 编写UserAction
@Namespace("/")
@ParentPackage("struts-default")
public class UserAction extends ActionSupportimplementsModelDriven<User>{
private Useruser = new User();
@Action(value="user_login", results={@Result(location="/product.jsp"),
@Result(name="INPUT", location="/login.jsp")})
public String login() {
// 调用UserService检查用户名密码
UserService userService =new UserServiceImpl();
User loginUser = userService.login(user.getUsername(), user.getPassword());
if(loginUser !=null) {
ServletActionContext.getRequest().getSession().setAttribute("user",loginUser);
return SUCCESS;
}
else {
addActionError("用户名或密码错误");
return INPUT;
}
}
@Override
public User getModel() {
returnuser;
}
}
Ø 编写product.jsp
<%@ page language="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<scripttype="text/javascript"src="${pageContext.request.contextPath}/js/jquery-1.8.3.js"></script>
<title>查看商品</title>
</head>
<body>
<ahref="javascript:void(0)"id="a">查看商品信息</a>
<divid="prod">
</div>
<scripttype="text/javascript">
$('#a').toggle(function() {
$.post('${pageContext.request.contextPath}/product_list',function(data) {
var html ='';
if(data.type == 0) {
alert(data.msg);
return;
}
html += '<table border="1" cellspacing="0"cellpadding="2">';
// 拼接表头
html += '<tr>';
html += ' <th>ID</th>';
html += ' <th>产品名称</th>';
html += ' <th>产品数量</th>';
html += ' <th>产品价格</th>';
html+= '</tr>';
for(var i = 0; i <data.content.length; ++i) {
html += ' <tr>';
html += ' <td>' + data.content[i].id +'</td>';
html += ' <td>' + data.content[i].name +'</td>';
html += ' <td>' + data.content[i].count +'</td>';
html += ' <td>' + data.content[i].price +'</td>';
html += ' </tr>';
}
html += '</table>';
$('#prod').html(html);
}, 'json');
}, function() {
// 清空元素
$('#prod').html('');
});
</script>
</body>
</html>
1.2 注解案例——请求显示商品信息
Ø 编写Product实体类
public class Product {
private Integerid;
private Stringname;
private Integercount;
private Doubleprice;
public Integer getId() {
returnid;
}
public void setId(Integer id) {
this.id =id;
}
public String getName() {
returnname;
}
public void setName(String name) {
this.name =name;
}
public Integer getCount() {
returncount;
}
public void setCount(Integer count) {
this.count =count;
}
public Double getPrice() {
returnprice;
}
public void setPrice(Double price) {
this.price =price;
}
}
Ø 编写统一响应结果Result类
public class Result<T> {
private int type; // 状态:0 - 错误, 1 - 正常
private List<T>content; // 返回到客户端的数据列表
private Stringmsg; // 错误信息
public int getType() {
returntype;
}
public void setType(inttype) {
this.type =type;
}
public List<T> getContent() {
returncontent;
}
public void setContent(List<T> content) {
this.content =content;
}
public String getMsg() {
returnmsg;
}
public void setMsg(String msg) {
this.msg =msg;
}
}
Ø 编写DAO
接口(ProductDao)
public interface ProductDao {
List<Product> findAll();
}
实现(ProductDaoImpl)
public class ProductDaoImpl implements ProductDao{
@Override
public List<Product> findAll(){
QueryRunner queryRunner =newQueryRunner(JdbcUtils.getDataSource());
try {
returnqueryRunner.query("select * from product",new BeanListHandler<Product>(Product.class));
} catch (SQLExceptione) {
e.printStackTrace();
}
return null;
}
}
Ø 编写Service
接口(ProductService)
public interface ProductService {
List<Product> findAll();
}
实现(ProductServiceImpl)
public class ProductServiceImpl implementsProductService{
@Override
public List<Product> findAll(){
ProductDao productDao =new ProductDaoImpl();
returnproductDao.findAll();
}
}
Ø 编写Interceptor
public class LoginInterceptor extendsMethodFilterInterceptor{
@Override
protected StringdoIntercept(ActionInvocationinvocation) throws Exception {
Object user =ServletActionContext.getRequest().getSession().getAttribute("user");
if(user !=null) {
returninvocation.invoke();
}
else {
Result result =new Result();
result.setType(0);
result.setMsg("权限不足");
ServletActionContext.getResponse().setCharacterEncoding("utf-8");
String json = JSONObject.toJSONString(result);
ServletActionContext.getResponse().getWriter().write(json);
return Action.NONE;
}
}
}
Ø 在struts.xml中配置拦截器、定义拦截器栈
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEstruts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constantname="struts.devMode"value="true"></constant>
<packagename="basic"extends="struts-default"namespace="/">
<interceptors>
<interceptorname="loginCheck"class="com.itheima.utils.LoginInterceptor"></interceptor>
<interceptor-stackname="authCheck">
<interceptor-refname="loginCheck"></interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
</package>
</struts>
Ø 编写Action
@Namespace("/")
@ParentPackage("basic")
public class ProductAction extends ActionSupport{
@Action(value="product_list", interceptorRefs=@InterceptorRef("authCheck"))
public String findAll()throws IOException {
ProductService productService =newProductServiceImpl();
List<Product> products =productService.findAll();
Result<Product> prodResult =newResult<Product>();
prodResult.setType(1);
prodResult.setContent(products);
String json = JSONObject.toJSONString(prodResult);
ServletActionContext.getResponse().setCharacterEncoding("utf-8");
ServletActionContext.getResponse().getWriter().write(json);
return NONE;
}
}
1.3 注解案例——显示商品信息
<%@ page language="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<scripttype="text/javascript"src="${pageContext.request.contextPath}/js/jquery-1.8.3.js"></script>
<title>查看商品</title>
</head>
<body>
<ahref="javascript:void(0)"id="a">查看商品信息</a>
<divid="prod">
</div>
<scripttype="text/javascript">
$('#a').toggle(function() {
$.post('${pageContext.request.contextPath}/product_list',function(data) {
var html ='';
if(data.type == 0) {
alert(data.msg);
return;
}
html += '<table border="1" cellspacing="0"cellpadding="2">';
// 拼接表头
html += '<tr>';
html += ' <th>ID</th>';
html += ' <th>产品名称</th>';
html += ' <th>产品数量</th>';
html += ' <th>产品价格</th>';
html += '</tr>';
for(var i = 0; i <data.content.length; ++i){
html += ' <tr>';
html += ' <td>' +data.content[i].id+ '</td>';
html += ' <td>' + data.content[i].name +'</td>';
html += ' <td>' + data.content[i].count +'</td>';
html += ' <td>' + data.content[i].price +'</td>';
html += ' </tr>';
}
html += '</table>';
$('#prod').html(html);
}, 'json');
}, function() {
// 清空元素
$('#prod').html('');
});
</script>
</body>
</html>
整体流程的难点解析:首先分为用户登录功能和商品展示功能 这两个模块, 对于用户登录 我们通过注解开发实现点击登录进入struts2的action类进行校验, 如果正确的话保存用户信息到session后跳转到有一个展示商品链接的页面 , 如果用户登录失败的话, 存域失败信息后返回登录页面提示.
商品展示功能模块: 首先点击展示商品的链接后我们希望实现展示商品列表的功能 , 点击链接进入struts2的action中进行数据库的查询将查询的数据存到一个新定义的有用户是否已登录状态的字段的类Result类中并且设置登录状态字段为已登录, 然后通过自定义的过滤器实现对没有用户session的情形进行登录状态的修改和相应的提示信息存域, 最后再页面对登录状态字段进行判断 , 分情况展示内容 , 从而实现对没有登录用户的权限验证.