(五)sturts2+spring整合
一、Spring与Struts的整合
1.1:加入Spring的jar包。
1.2:加入Struts的jar包。
1.3:加入Struts与Spring的整合jar//struts2-spring-plugin-2.3.28.jar。
- 功能:将Struts中的Action对象交给Spring来管理。Spring可以往Action中依赖注入对象。
1.4 : 配置文件
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>spring_struts2_1</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <filter> <filter-name>encoding</filter-name> <filter-class>filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <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
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <constant name="struts.i18n.encoding" value="UTF-8"></constant> <constant name="struts.multipart.maxSize" value="209715200"></constant> <constant name="struts.action.extension" value="action,do,"></constant> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <constant name="struts.devMode" value="true" /> <constant name="struts.i18n.reload" value="true"></constant> <constant name="struts.ui.theme" value="simple" /> <constant name="struts.configuration.xml.reload" value="true"></constant> <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> <constant name="struts.handle.exception" value="true"></constant> <!-- 配置这2个常量。这样Struts的对象才能交给Spring来管理。并且Spring对象注入的方式是根据名称来注入--> <constant name="struts.objectFactory" value="spring"></constant> <constant name="struts.objectFactory.spring.autoWire" value="name"></constant> <package name="default" namespace="/" extends="struts-default"> <action name="testAction" class="action.TestAction"> <result name="main">main.jsp</result> </action> </package> </struts>
- 注意配置<constant name="struts.objectFactory" value="spring"></constant>
- <constant name="struts.objectFactory.spring.autoWire" value="name"></constant> 这两个常量,第一个用于struts的action交给spring管理,并且spring注入的方式是根据名称来注入,比如TesetAction中有一个成员属性UserService userService(必须有set方法) 然后在spring.xml中配置一个bean 的id为"userService"的(必须与acton中的成员属性名一致),这样spring.xml的bean会自动关联到TestAction的userService里了。
spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <constructor-arg index="0" name="driverClassName" value="com.mysql.jdbc.Driver" ></constructor-arg> <constructor-arg index="1" name="url" value="jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=UTF-8" ></constructor-arg> <constructor-arg index="2" name="username" value="root"></constructor-arg> <constructor-arg index="3" name="password" value=""></constructor-arg> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="userService" class="service.UserServiceImpl"> <property name="userdao" > <bean class="dao.UserDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> </property> </bean> </beans>
1.5 写action、servlet、dao等
二、案例
- 配置文件:web.xml、struts.xml、spring.xml如上面所述。
- index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%String path=request.getContextPath(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="<%=path %>/testAction!list">spring和struts2整合</a> </body> </html>
- TestAction.java
package action; import java.util.List; import org.apache.struts2.components.ActionComponent; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.util.ValueStack; import bean.UserBean; import service.UserServiceI; import util.BaseAction; public class TestAction extends BaseAction{ private UserServiceI userService; public void setUserService(UserServiceI userService) { this.userService = userService; } @Override public String execute() throws Exception { return null; } public String list(){ List<UserBean> userList=userService.getUserList(); ValueStack valuestack=ActionContext.getContext().getValueStack(); valuestack.set("userList", userList); return "main"; } }
-
UserServiceI .java
package service; import java.util.List; import bean.UserBean; public interface UserServiceI { List<UserBean> getUserList(); }
- UserServiceImpl.java
package service; import java.util.List; import bean.UserBean; import dao.UserDao; public class UserServiceImpl implements UserServiceI { private UserDao userdao; public void setUserdao(UserDao userdao) { this.userdao = userdao; } public List<UserBean> getUserList() { return userdao.getUserList(); } }
- UserDao.java
package dao; import java.util.List; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import bean.UserBean; public class UserDao extends JdbcDaoSupport{ public List<UserBean> getUserList() { String sql="select * from user"; List<UserBean> userList=this.getJdbcTemplate().query(sql, new BeanPropertyRowMapper<UserBean>(UserBean.class)); return userList; } }
- UserBean.java
package bean; public class UserBean { private String userName; private int age; private String sex; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
- BaseAction.java
package util; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionSupport; public abstract class BaseAction extends ActionSupport implements ServletRequestAware, ServletResponseAware, ServletContextAware { protected HttpServletRequest request; protected HttpServletResponse response; protected ServletContext context; protected HttpSession session; protected PrintWriter out; public void setServletRequest(HttpServletRequest request) { this.request = request; if (this.request != null) { this.session = this.request.getSession(); } } public void setServletResponse(HttpServletResponse response) { this.response = response; if (this.response != null) { try { this.response.setContentType("text/html"); this.out = this.response.getWriter(); } catch (IOException e) { e.printStackTrace(); } } } public void setServletContext(ServletContext context) { this.context = context; } public abstract String execute() throws Exception; }
EncodingFilter.java
package filter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; /** * 此过滤器用于解决get和post请求中问乱码的问题。 */ public class EncodingFilter implements Filter { public EncodingFilter() { } public void destroy() { } /** * 要解决乱码问题首先区别对待POST方法和GET方法, * 1.如果是POST方法,则用request.setCharacterEncoding("UTF-8"); 即可 * 2.如果是GET方法,则麻烦一些,需要用decorator设计模式包装request对象来解决 */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)req; HttpServletResponse response=(HttpServletResponse)res; //获取request请求是get还是post String method=request.getMethod(); if(method.equals("GET") || method.equals("get")){ //注意大小写都要判断,一般来说是大写的GET /** * request请求为get请求,则用包装类对request对象的getParameter方法进行覆盖。 */ response.setContentType("text/html;charset=UTF-8"); MyGetHttpServletRequestWrapper requestWrapper=new MyGetHttpServletRequestWrapper(request); chain.doFilter(requestWrapper, response); }else{ //post请求 response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); chain.doFilter(request, response); } } public void init(FilterConfig fConfig) throws ServletException { } } class MyGetHttpServletRequestWrapper extends HttpServletRequestWrapper{ HttpServletRequest request; public MyGetHttpServletRequestWrapper(HttpServletRequest request) { super(request); this.request=request; } /** * servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper, * (HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 * request对象的对应方法) 以避免用户在对request对象进行增强时需要实现request接口中的所有方法。 * 所以当需要增强request对象时,只需要写一个类继承HttpServletRequestWrapper类,然后在重写需要增强的方法即可 * 具体步骤: *1.实现与被增强对象相同的接口 *2、定义一个变量记住被增强对象 *3、定义一个构造函数,接收被增强对象 4、覆盖需要增强的方法 5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法 */ @Override public String getParameter(String name) { String old_value=super.getParameter(name); String new_value=null; if(old_value!=null && !old_value.equals("")){ try { new_value=new String(old_value.getBytes("ISO-8859-1"),"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return new_value; } @Override public String[] getParameterValues(String name) { String[] old_value=request.getParameterValues(name); String[] new_value=new String[old_value.length]; if(old_value!=null && !old_value.equals("")){ String temp_value=null; for(int i=0;i<old_value.length;i++){ try { temp_value=new String(old_value[i].getBytes("ISO-8859-1"),"UTF-8"); new_value[i]=temp_value; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } return new_value; } /** * 使用struts封装的作用域,把reuqest、session、servletContext作用域封装成Map, * 所以struts的OGNL表达式在获取请求参数值的时候是并不是调用request.getParameter()或getParameterValues方法 * 而是调用request.getParameterMap()方法。 * 要解决struts2中OGNL获取parameters中请求参数值乱码的问题,只要覆盖request.getParameterMap()方法既可。 */ @Override public Map getParameterMap() { try { if (!this.request.getMethod().equals("GET")) {// 判断是否是get请求方式,不是get请求则直接返回 return this.request.getParameterMap(); } Map<String, String[]> map = this.request.getParameterMap(); // 接受客户端的数据 Map<String, String[]> newmap = new HashMap(); for (Map.Entry<String, String[]> entry : map.entrySet()) { String name = entry.getKey(); String values[] = entry.getValue(); if (values == null) { newmap.put(name, new String[] {}); continue; } String newvalues[] = new String[values.length]; for (int i = 0; i < values.length; i++) { String value = values[i]; value = new String(value.getBytes("iso8859-1"), this.request.getCharacterEncoding()); newvalues[i] = value; // 解决乱码后封装到Map中 } newmap.put(name, newvalues); } return newmap; } catch (Exception e) { throw new RuntimeException(e); } } }
- main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <table border="1"> <tr> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> <s:iterator value="userList"> <tr> <td><s:property value="userName" /></td> <td><s:property value="age" /></td> <td><s:property value="sex" /></td> </tr> </s:iterator> </table> </body> </html>
结果:
所有代码都在这里: 链接 (数据库文件user.sql在webContent里)