最近接触了 Java 开发,相比 Android 开发,技术栈的差异还是蛮大的,许多新的知识需要学习,这里记录一下开发环境的搭建过程,对于新手来说这个过程可能并不会太容易,开发工具自然是 IntelliJ IDEA,毕竟和 Android Studio 的体验类似,个人感觉比 eclipse 更好用。
一、创建 Maven web 项目
首先创建基于 Maven 的 web 项目,以方便后续的项目管理,然后再整合 SSM 框架。由于 IntelliJ IDEA 已经集成了 Maven 插件,可以不用额外安装,创建 Maven web 项目基本的步骤如下:
1、选择 maven-archetype-webapp
2、GroupId 可以按照包名的规则填写,ArtifactId 可以填写项目名称
3、选择 Maven 路径
4、确定最终的项目名称及路径等信息
5、上一步 Finish 后就开始 Maven web 项目构建了,注意右下角会有如下提示,选择 Enable Auto-Import 即可,构建可能要一小段时间,不妨起来活动下身体。
6、构建成功后的项目结构如下,这里需要再手动完善下目录结构,在 main 下创建 java、resources目录(按需创建即可)
7、为了创建的目录更好的被编译器识别,打开 Project Structure 分别标记先创建的目录
8、Java web 项目要运行自然需要一个 web 容器,这里使用 Tomcat,要先安装好,然后通过 Edit Configurations 选项打开如下页面进行配置
9、Tomcat 配置,给 Tomcat 取个名字,选择已安装的 Tomcat 版本,运行 web 项目的浏览器,占用的端口号等
10、切换到 Deployment 标签
11、部署 Tomcat,还可以配置 Application context 即 web 项目的默认访问路径,这里先不配置,到这里 web 项目就可以运行了
12、可点击编译器上边的绿三角还运行项目,不出意外的话可以看到如下页面,这就成功的迈出了第一步。如果上一步配置了Application context,例如 /myjavaee,则通过 http://localhost:8080/myjavaee 同样可以访问到如下页面。
一、整合 SSM 框架
上边已经成功的创建了 Maven web 项目,下面开始整合 SSM 框架,即 Spring MVC + Spring + MyBatis,这里采用 xml 的配置方式,最终的目录结构如下,需要的文件自行创建。
1、首先在 pom.xml 中引入相关库的 Maven 依赖,关键的部分如下:
<properties>
<spring.version>4.3.23.RELEASE</spring.version>
</properties>
<dependencies>
<!--Spring IoC、Bean装配-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Spring整合数据库连接-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--web开发-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--web开发的mvc支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--MyBatis持久化框架-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--MyBatis整合Spring的框架-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!--JSTL支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--Spring默认的JSON解析框架-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
2、web.xml、dispatcher-servlet.xml、applicationContext.xml是比较关键的几个配置文件
web.xml 作为 Web 应用的核心配置文件,会加载其它两个:
<!--Spring IoC配置文件路径-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!--配置ContextLoaderListener用来初始化Spring IoC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置DispatcherServlet-->
<!--注意:Spring MVC框架会根据servlet-name配置,找到/WEB-INF/dispatcher-servlet.xml作为配置文件载入Web工程中-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<!--拦截用户请求的前端控制器-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--<init-param>-->
<!--<param-name>contextConfigLocation</param-name>-->
<!--<param-value>classpath:spring-mvc.xml</param-value>-->
<!--</init-param>-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--拦截所有请求-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
dispatcher-servlet.xml 主要是 Spring MVC 相关的配置:
<!-- 使用注解驱动 Spring MVC -->
<mvc:annotation-driven/>
<!-- 扫描控制器包中的类 -->
<context:component-scan base-package="com.shh.myjavaee.controller"/>
<!-- 静态资源处理
对进入DispatcherServlet的URL进行筛查,
如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,
如果不是静态资源的请求,才由DispatcherServlet继续处理-->
<mvc:default-servlet-handler/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.shh.myjavaee.interceptor.CommonInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!-- 定义视图解析器 -->
<!-- 找到Web工程/WEB-INF/JSP文件夹,且文件结尾为jsp的文件作为映射 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
applicationContext.xml 主要进行了 MyBatis 数据持久化相关Bean的配置,以及 Service Bean 的初始化:
<!--扫描service目录下的类,并将对象存储在IoC容器中-->
<context:component-scan base-package="com.shh.myjavaee.service"/>
<!--使用注解驱动-->
<!--<context:annotation-config/>-->
<!--加载数据库配置的属性文件-->
<context:property-placeholder location="classpath:jdbc.properties" ignore-resource-not-found="true"/>
<!--配置数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<!--连接池的最大数据库连接数 -->
<property name="maxActive" value="255"/>
<!--最大等待连接中的数量 -->
<property name="maxIdle" value="5"/>
<!--最大等待毫秒数 -->
<property name="maxWait" value="10000"/>
</bean>
<!--集成MyBatis-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--MyBatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--MyBatis映射器目录-->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
</bean>
<!--采用自动扫描方式创建 mapper bean-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描的目录-->
<property name="basePackage" value="com.shh.myjavaee.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描使用了Repository注解的类-->
<property name="annotationClass" value="org.springframework.stereotype.Repository"/>
</bean>
<!--配置数据源事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置声明式事物的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
3、MyBatis 映射器
applicationContext.xml 中已经完成了 MyBatis 的相关配置,这里将 RoleMapper.xml 映射器文件放到了 resources目录下,和接口文件分开:
<mapper namespace="com.shh.myjavaee.dao.RoleDao">
<resultMap id="roleMap" type="role">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="note" column="note"/>
</resultMap>
<insert id="insertRole" parameterType="role" useGeneratedKeys="true" keyProperty="id">
insert into t_role (role_name, note)
values (#{roleName}, #{note})
</insert>
<select id="getRole" parameterType="long" resultMap="roleMap">
select id, role_name, note
from t_role
where id = #{id}
</select>
<select id="getAllRole" resultMap="roleMap">
select id, role_name, note
from t_role
</select>
<update id="updateRole" parameterType="role">
update t_role
set role_name = #{roleName},
note = #{note}
where id = #{id}
</update>
<delete id="deleteRole" parameterType="long">
delete
from t_role
where id = #{id}
</delete>
</mapper>
对应的接口文件 RoleDao 如下:
@Repository
public interface RoleDao {
public int insertRole(Role role);
public Role getRole(Long id);
public List<Role> getAllRole();
public int deleteRole(Long id);
public int updateRole(Role role);
}
使用了 @Repository 注解会被 Spring 扫描以生成 Mapper 对象,即 RoleDao 对象,方便依赖注入。
使用 MyBatis 时,我们有时候难以避免的在 xml 文件和接口文件之间切换跳转,查找对应的关系,Free Mybatis 可以非常方便的帮我们完成这个工作,值得一试。
使用 MyBatis 时,一般用 log4j 打印 sql 日志,但是需要提取 sql 并完成参数的填充还是一件麻烦事。没关系,MyBatis log 框架就是专门干这个事的,值得拥有。
4、服务类
在 Spring MVC 中一般通过服务类来进行具体的数据库操作逻辑,然后在控制器中使用服务类。服务类一般通过接口模式实现,方便扩展:
public interface RoleService {
public Role getRole(Long id);
public List<Role> getAllRole();
}
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleDao roleDao = null;
@Override
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public Role getRole(Long id) {
return roleDao.getRole(id);
}
@Override
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public List<Role> getAllRole() {
return roleDao.getAllRole();
}
}
使用了 @Service 注解,同样会被 Spring 扫描生成 Bean 保存在 IoC 容器中,为后续的依赖注入准备。同时用 @Autowired 注解实现了 roleDao 对象的注入。@Transactional 是 Spring 事务配置注解。
5、控制器
控制器是 Spring MVC 的核心,主要的功能是获取请求参数,根据参数处理业务逻辑,最后绑定模型和视图并返回。我们编写的控制器类如下:
@Controller
@RequestMapping("/role")
public class RoleController {
@Autowired
private RoleService roleService;
@RequestMapping("/getRoles")
public ModelAndView getRoles() {
List<Role> roles = roleService.getAllRole();
ModelAndView mv = new ModelAndView();
mv.setViewName("role");
mv.addObject("roles", roles);
return mv;
}
@RequestMapping("/getRole/{id}")
@ResponseBody
public Object getRole(@PathVariable("id") long id) {
Role role = roleService.getRole(id);
return role;
}
}
首先控制器类要用 @Controller 注解标注,之前已经在 dispatcher-servlet.xml 中配置要扫描控制器类。同时还在类和方法上使用了 @RequestMapping 注解,用来指定 URI 对应哪个请求处理方法。
6、视图渲染
Spring MVC 默认使用 JstlView 进行视图渲染,前边控制器类的第一个方法里,通过 mv.setViewName("role")
设置了逻辑视图名 role,根据 dispatcher-servlet.xml 中视图解析器的配置,会用 /WEB-INF/jsp/role.jsp文件去相应对应请求,通过 mv.addObject("roles", roles)
添加了模型数据会传递到 jsp 中,用 EL 读取。例如:${roles}
role.jsp 的内容如下:
<%@ page pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>角色信息</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<td>编号</td>
<td>名称</td>
<td>备注</td>
</tr>
</thead>
<c:forEach items="${roles}" var="role">
<tr>
<td><c:out value="${role.id}"/></td>
<td><c:out value="${role.roleName}"/></td>
<td><c:out value="${role.note}"/></td>
</tr>
</c:forEach>
</table>
</body>
</html>
就是显示一个 table。启动 web 应用,在浏览器输入 http://localhost:8080/role/getRoles 就可以看到如下页面:
返回 JSON 格式的数据也是比较常见的,在控制器类的第二个方法中使用了 @ResponseBody 注解,这样会把返回的数据通过 JSON视图转换成JSON格式的数据,在浏览器输入 http://localhost:8080/role/getRole/1 可以看到:
到这里,已经完成了框架的整合,基本的流程已经走通了,当然这些只是基础内容,SSM 框架中还有更多的内容值得我们去深入了解。
文中demo地址:https://github.com/SheHuan/MyJavaEE