前言
本文不使用spring XML,而是采用Java配置SSM框架的形式实现了基本的增删改查。
本文中的源码继承自https://www.cnblogs.com/hanzx/p/10016468.html中的程序,删除掉了webapp文件夹,里面的模板全部转移到resources下,其余文件均已删除。
核心框架已升级。spring系列已升级使用5.0.1,mybatis使用3.4.5,mybatis-spring使用1.3.1。
名词解释
SSM框架:springMVC、spring、mybatis
thymeleaf:一个与Velocity、FreeMarker类似的模板引擎
jquery:一个快速、简洁的JavaScript框架
程序结构
程序源码
pom.xml
4.0.0
org.hanzx
webssmwithoutxml
1.0-SNAPSHOT
war
webssmwithoutxml Maven Webapp
http://www.example.com
UTF-8
1.8
1.8
5.0.1.RELEASE
1.6.6
1.2.12
5.1.35
2.9.2
junit
junit
4.11
test
org.springframework
spring-core
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-aspects
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-test
${spring.version}
test
org.springframework
spring-webmvc
${spring.version}
mysql
mysql-connector-java
${mysql.version}
com.alibaba
druid
0.2.23
com.alibaba
fastjson
1.1.41
log4j
log4j
${log4j.version}
org.slf4j
slf4j-api
${slf4j.version}
ch.qos.logback
logback-classic
1.1.2
ch.qos.logback
logback-core
1.1.2
org.logback-extensions
logback-ext-spring
0.1.1
org.mybatis
mybatis
3.4.5
org.mybatis
mybatis-spring
1.3.1
javax.servlet
javax.servlet-api
3.0.1
javax.servlet.jsp
javax.servlet.jsp-api
2.3.2-b01
javax.servlet
jstl
1.2
org.thymeleaf
thymeleaf-spring5
3.0.9.RELEASE
com.fasterxml.jackson.core
jackson-core
${jackson.version}
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
webssmwithoutxml
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
package-info.java(使用new-file创建的,用java class无法创建)
/**package级别的注解。。。不配置的话,WebInitializer里的getServletMappings方法报黄*/@NonNullApipackageorg.hanzx.config;import org.springframework.lang.NonNullApi;
springConfig.java
packageorg.hanzx.config;import org.springframework.context.annotation.*;importorg.springframework.stereotype.Controller;/**spring配置类
* 注解扫描基础package,排除controller*/@Configuration
@ComponentScan(basePackages= {"org.hanzx"},
excludeFilters= {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})
@Import(value= SpringMybatisConfig.class)public classSpringConfig {
}
SpringMvcConfig.java
packageorg.hanzx.config;importorg.hanzx.interceptors.CORSInterceptor;import org.springframework.context.annotation.*;importorg.springframework.http.MediaType;importorg.springframework.stereotype.Controller;importorg.springframework.web.accept.ContentNegotiationManagerFactoryBean;import org.springframework.web.servlet.config.annotation.*;importorg.thymeleaf.spring5.SpringTemplateEngine;importorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;importorg.thymeleaf.spring5.view.ThymeleafViewResolver;importjava.util.Properties;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {"org.hanzx.controller"}, useDefaultFilters = false,
includeFilters= {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})public class SpringMvcConfig implementsWebMvcConfigurer {
@BeanpublicContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean(){
ContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean= newContentNegotiationManagerFactoryBean();//扩展名至mimeType的映射,即 /userEntity.json => application/json
contentNegotiationManagerFactoryBean.setFavorPathExtension(true);//用于开启 /userinfo/123?format=json 的支持
contentNegotiationManagerFactoryBean.setFavorParameter(true);
contentNegotiationManagerFactoryBean.setParameterName("format");//是否忽略Accept Header
contentNegotiationManagerFactoryBean.setIgnoreAcceptHeader(false);//扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用
Properties properties = newProperties();
properties.setProperty("json", "application/json");
properties.setProperty("xml", "application/xml");
properties.setProperty("html", "text/html");
contentNegotiationManagerFactoryBean.setMediaTypes(properties);//默认的content type
contentNegotiationManagerFactoryBean.setDefaultContentType(MediaType.TEXT_HTML);returncontentNegotiationManagerFactoryBean;
}//这个是旧版用的,新版不要它///**当在web.xml 中 DispatcherServlet使用 / 映射时,能映射静态资源*///@Override//public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {//
//}
/**静态资源映射*/@Overridepublic voidaddResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}/**对模型视图添加前后缀及其他*/@BeanpublicSpringResourceTemplateResolver springResourceTemplateResolver(){
SpringResourceTemplateResolver springResourceTemplateResolver= newSpringResourceTemplateResolver();
springResourceTemplateResolver.setPrefix("/templates/");
springResourceTemplateResolver.setSuffix(".html");
springResourceTemplateResolver.setCharacterEncoding("UTF-8");
springResourceTemplateResolver.setOrder(1);
springResourceTemplateResolver.setTemplateMode("HTML5");
springResourceTemplateResolver.setCacheable(false);returnspringResourceTemplateResolver;
}
@BeanpublicSpringTemplateEngine springTemplateEngine(){
SpringTemplateEngine springTemplateEngine= newSpringTemplateEngine();
springTemplateEngine.setTemplateResolver(springResourceTemplateResolver());returnspringTemplateEngine;
}
@BeanpublicThymeleafViewResolver thymeleafViewResolver(){
ThymeleafViewResolver thymeleafViewResolver= newThymeleafViewResolver();
thymeleafViewResolver.setTemplateEngine(springTemplateEngine());
thymeleafViewResolver.setCharacterEncoding("UTF-8");returnthymeleafViewResolver;
}/**拦截器 跨域拦截器*/@Overridepublic voidaddInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(newCORSInterceptor());
}/*** 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页*/@Overridepublic voidaddViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
}
SpringMybatisConfig.java
packageorg.hanzx.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.mybatis.spring.SqlSessionFactoryBean;importorg.mybatis.spring.annotation.MapperScan;importorg.mybatis.spring.mapper.MapperScannerConfigurer;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.beans.factory.config.PropertyPlaceholderConfigurer;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;importorg.springframework.context.annotation.PropertySources;importorg.springframework.context.support.PropertySourcesPlaceholderConfigurer;importorg.springframework.core.io.support.PathMatchingResourcePatternResolver;importorg.springframework.core.io.support.ResourcePatternResolver;importorg.springframework.jdbc.datasource.DataSourceTransactionManager;importorg.springframework.transaction.annotation.EnableTransactionManagement;importjava.io.IOException;importjava.sql.SQLException;
@Configuration
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement
@MapperScan("org.hanzx.dao")//扫描mapper
public classSpringMybatisConfig {
@Value("${jdbc_driverClassName}")privateString driverClassName;
@Value("${jdbc_url}")privateString url;
@Value("${jdbc_username}")privateString userName;
@Value("${jdbc_password}")privateString password;
@Value("${initialSize}")privateInteger initialSize;
@Value("${minIdle}")privateInteger minIdle;
@Value("${maxActive}")privateInteger maxActive;
@Value("${maxWait}")privateLong maxWait;
@Value("${timeBetweenEvictionRunsMillis}")privateLong timeBetweenEvictionRunsMillis;
@Value("${minEvictableIdleTimeMillis}")privateLong minEvictableIdleTimeMillis;
@Value("${validationQuery}")privateString validationQuery;
@Value("${testWhileIdle}")privateBoolean testWhileIdle;
@Value("${testOnBorrow}")privateBoolean testOnBorrow;
@Value("${testOnReturn}")privateBoolean testOnReturn;
@Value("${poolPreparedStatements}")privateBoolean poolPreparedStatements;
@Value("${maxPoolPreparedStatementPerConnectionSize}")privateInteger maxPoolPreparedStatementPerConnectionSize;
@Value("${filters}")privateString filters;//这个无须使用,直接配@PropertySource注解就可以了///** 这个bean必须配置而且必须是静态方法,如果不配置就不能进行@Value的属性注入*///@Bean//public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {//ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();//PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();//configurer.setLocation(resourcePatternResolver.getResource("classpath:jdbc.properties"));//return configurer;//}//这个旧了,不再使用了,spring 3.1以后推荐使用PropertySourcesPlaceholderConfigurer//@Deprecated//@Bean//public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() throws IOException {//ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();//PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();//configurer.setLocation(resourcePatternResolver.getResource("classpath:jdbc.properties"));//return configurer;//}
/**配置数据源 ,使用的alibba的数据库*/@Bean(initMethod= "init", destroyMethod = "close")public DruidDataSource dataSource() throwsSQLException {
DruidDataSource druidDataSource= newDruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(userName);
druidDataSource.setPassword(password);
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
druidDataSource.setValidationQuery(validationQuery);
druidDataSource.setTestWhileIdle(testWhileIdle);
druidDataSource.setTestOnBorrow(testOnBorrow);
druidDataSource.setTestOnReturn(testOnReturn);
druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
druidDataSource.setFilters(filters);returndruidDataSource;
}/**spring和MyBatis完美整合,不需要mybatis的配置映射文件*/@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean() throwsSQLException, IOException {
ResourcePatternResolver resourcePatternResolver= newPathMatchingResourcePatternResolver();
SqlSessionFactoryBean sqlSessionFactoryBean= newSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath:mapper/*.xml"));returnsqlSessionFactoryBean;
}//不能使用这个,这东西先于properties加载,会导致properties文件读不出数据,改用@MapperScan扫描dao///**DAO接口所在包名,Spring会自动查找其下的类 ,自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,//* 只要Mapper接口类和Mapper映射文件对应起来就可以了*///@Bean//public MapperScannerConfigurer mapperScannerConfigurer(){//MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();//mapperScannerConfigurer.setBasePackage("org.hanzx.dao");//mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");//return mapperScannerConfigurer;//}
/**(事务管理)transaction manager, use JtaTransactionManager for global tx 配置事务管理器*/@Beanpublic DataSourceTransactionManager dataSourceTransactionManager() throwsSQLException {
DataSourceTransactionManager dataSourceTransactionManager= newDataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource());returndataSourceTransactionManager;
}
}
WebInitializer.java
packageorg.hanzx.config;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;/*** 在Servlet3.0以上的环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果发现则用它来配置 * Servlet容器,Spring提供了这个接口的实现名为SpringServletContainerInitializer,这个类反过来又会查找实现了 * WebApplicationInitializer的类并把配置任务交给它们来完成,AbstractAnnotationConfigDispatcherServletInitializer的祖先类已 * 对该接口进行了实现*/
public class WebInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {private final static Logger LOG = LoggerFactory.getLogger(WebInitializer.class);/*** 该方法用于配置ContextLoaderListener创建的应用上下文的bean,相当于web.xml配置中的
* * org.springframework.web.ContextLoaderListener 差异:
* * 注解配置需要添加的是配置类
* * 文件配置ContextLoaderListener在创建时自动查找WEB-INF下的applicationContext.xml文件,
* 当文件不止1个时需通过设置 * 上下文参数(context-param)配置contextConfigLocation的值
* * *@return带有@Configuration注解的类(这些类将会用来配置ContextLoaderListener创建的应用上下文的bean)*/@Overrideprotected Class>[] getRootConfigClasses() {
LOG.info("------root配置类初始化------");return new Class>[]{SpringConfig.class};
}/*** 该方法用于配置DispatcherServlet所需bean,配置类一般用于生成控制层的bean(因Controller中一般包含对参数的设置及数据的返回) * 相当于web.xml对Spring * MVC的配置…org.springframework.web.servlet.DispatcherServlet…
* 配置类如WebConfig.class相当于DispatcherServlet中contetConfigLocation参数对应的配置文件 * *@return带有@Configuration注解的类(这些类将会用来配置DispatcherServlet应用上下文中的bean)*/@Overrideprotected Class>[] getServletConfigClasses() {
LOG.info("------web配置类初始化------");return new Class>[]{SpringMvcConfig.class};
}
@OverrideprotectedString[] getServletMappings() {
LOG.info("------映射根路径初始化------");return new String[]{"/"};//请求路径映射,将路径映射到DispatcherServlet上,这里可以配置成/* 拦截所有
}
}
UserController.java
packageorg.hanzx.controller;importorg.hanzx.model.UserModel;importorg.hanzx.service.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.ui.ModelMap;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")public classUserController {private finalUserService userService;private String prefix = "user/";
@AutowiredpublicUserController(UserService userService) {this.userService =userService;
}//@RequestMapping(value="/getAllUser")//@ResponseBody//public List getAllUser(){//return userService.getAllUser();//}//
//@RequestMapping(value="/addUser")//@ResponseBody//public boolean addUser(UserModel userModel){//userService.addUser(userModel);//return true;//}//
//@RequestMapping(value="/updateUser")//@ResponseBody//public boolean updateUser(UserModel userModel){//userService.updateUser(userModel);//return true;//}//
//@RequestMapping(value="/deleteUser")//@ResponseBody//public boolean deleteUser(@RequestParam(value = "ids[]") Integer[] ids){//userService.deleteUser(ids);//return true;//}//@RequestMapping(value="/getUserListForm")//public String getUserListForm(){//return prefix + "user_list";//}
@RequestMapping(value="/getAllUser")publicString getAllUser(ModelMap modelMap){
modelMap.put("userModelList", userService.getAllUser());return prefix + "user_list";
}
@RequestMapping(value="/getUserDetailForm")publicString getUserDetailForm(ModelMap modelMap, Integer id){if (id != null){
modelMap.put("userModel", userService.getUserById(id));
}return prefix + "user_detail";
}
@RequestMapping(value="/addUser")publicString addUser(UserModel userModel){
userService.addUser(userModel);return "redirect:getAllUser";
}
@RequestMapping(value="/updateUser")publicString updateUser(UserModel userModel){
userService.updateUser(userModel);return "redirect:getAllUser";
}
@RequestMapping(value="/deleteUser")
@ResponseBodypublic boolean deleteUser(@RequestParam(value = "ids[]") Integer[] ids){
userService.deleteUser(ids);return true;
}
}
UserDao.java
packageorg.hanzx.dao;importorg.hanzx.entity.UserEntity;importorg.springframework.stereotype.Repository;importjava.util.List;
@Repositorypublic interfaceUserDao {
ListgetAllUser();voidaddUser(UserEntity userEntity);
UserEntity getUserById(Integer id);voidupdateUser(UserEntity userEntity);voiddeleteUserById(Integer id);
}
UserEntity.java
packageorg.hanzx.entity;public classUserEntity {privateInteger id;privateString name;privateInteger age;privateString password;publicInteger getId() {returnid;
}public voidsetId(Integer id) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicInteger getAge() {returnage;
}public voidsetAge(Integer age) {this.age =age;
}publicString getPassword() {returnpassword;
}public voidsetPassword(String password) {this.password =password;
}
}
CORSInterceptor.java
packageorg.hanzx.interceptors;importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;public class CORSInterceptor extendsHandlerInterceptorAdapter {
@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throwsException {
System.out.println("拦截请求: " +request.getServletPath());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.setHeader("Access-Control-Allow-Headers","Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed", "1");return true;
}
}
UserModel.java
packageorg.hanzx.model;public classUserModel {privateInteger id;privateString name;privateInteger age;privateString password;publicInteger getId() {returnid;
}public voidsetId(Integer id) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicInteger getAge() {returnage;
}public voidsetAge(Integer age) {this.age =age;
}publicString getPassword() {returnpassword;
}public voidsetPassword(String password) {this.password =password;
}
}
UserServiceImpl.java
packageorg.hanzx.service.impl;importorg.hanzx.dao.UserDao;importorg.hanzx.entity.UserEntity;importorg.hanzx.model.UserModel;importorg.hanzx.service.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.ArrayList;importjava.util.List;
@Servicepublic class UserServiceImpl implementsUserService{private finalUserDao userDao;
@AutowiredpublicUserServiceImpl(UserDao userDao) {this.userDao =userDao;
}
@Overridepublic ListgetAllUser() {
List userEntityList =userDao.getAllUser();
List userModelList = new ArrayList<>();for(UserEntity userEntity : userEntityList){
UserModel userModel= newUserModel();
userModel.setName(userEntity.getName());
userModel.setId(userEntity.getId());
userModel.setAge(userEntity.getAge());
userModelList.add(userModel);
}returnuserModelList;
}
@Overridepublic voidaddUser(UserModel userModel) {
UserEntity userEntity= newUserEntity();
userEntity.setName(userModel.getName());
userEntity.setAge(userModel.getAge());
userEntity.setPassword(userModel.getPassword());
userDao.addUser(userEntity);
}
@OverridepublicUserModel getUserById(Integer id) {
UserEntity userEntity=userDao.getUserById(id);
UserModel userModel= newUserModel();
userModel.setAge(userEntity.getAge());
userModel.setId(userEntity.getId());
userModel.setName(userEntity.getName());
userModel.setPassword(userEntity.getPassword());returnuserModel;
}
@Overridepublic voidupdateUser(UserModel userModel) {
UserEntity userEntity=userDao.getUserById(userModel.getId());
userEntity.setPassword(userModel.getPassword());
userEntity.setAge(userModel.getAge());
userEntity.setName(userModel.getName());
userDao.updateUser(userEntity);
}
@Overridepublic voiddeleteUser(Integer[] ids) {for(Integer id : ids){
userDao.deleteUserById(id);
}
}
}
UserService.java
packageorg.hanzx.service;importorg.hanzx.model.UserModel;importjava.util.List;public interfaceUserService {
ListgetAllUser();voidaddUser(UserModel userModel);
UserModel getUserById(Integer id);voidupdateUser(UserModel userModel);voiddeleteUser(Integer[] ids);
}
UserMapper.xml
SELECT * FROM user;
INSERT USER VALUES (null, #{name}, #{age}, #{password});
SELECT * FROM user WHERE user.id = #{id};
UPDATE user SET name = #{name}, age = #{age}, password = #{password} WHERE id = #{id};
DELETE FROM user where id = #{id};
user_detail.html
Title