简体   繁体   中英

Access to HttpServletRequest and HttpServletResponse in Java Spring Service

I have an emailService implementation in my Java Spring Boot project. To send email, I use JavaMailSender. In my service I need an access to HttpServletRequest and HttpServletResponse in order to instantiate WebContext. Now I am passing these 2 - request and response through my mailsender methods what sounds like a bad idea. I would like to have them in my service so I can call methods in my mailsender with only 2 variables: what email template to use and a map of variables that will be printed on that email. Is there a way to instantiate request and response in my service? Can I somehow autowire them in the service? Thats how my service looks like:

@Service
@Qualifier("MailSender")
public class MailSenderService {

@Autowired 
private JavaMailSender mailSender;

@Autowired 
private ServletContextTemplateResolver emailTemplateResolver;


public boolean sendMail(HttpServletRequest request, HttpServletResponse     
response, HashMap<String, String> info, String template) throws 
MessagingException, IOException{

    final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
    final MimeMessageHelper message = new 
    MimeMessageHelper(mimeMessage,true, "UTF-8"); // true = multipart

        message.setFrom("sender@example.com");
        message.setTo("mymail@example.com");
        message.setSubject("This is the message subject");
        TemplateEngine engine = new TemplateEngine();
        engine.setTemplateResolver(emailTemplateResolver);
        WebContext ctx =  new WebContext(request, response, 
        request.getServletContext(), request.getLocale());

        ctx.setVariable("info", info);


    try{        
        String messageContent=  engine.process(template, ctx);
        mimeMessage.setContent(tt, "text/html; charset=utf-8");

    }catch(Exception e){
        e.printStackTrace();
    }

    this.mailSender.send(mimeMessage);
    return true;

}
}

If the class is request scoped you can autowire it as follows :

@Autowired private HttpServletRequest request;

Cheers..

You should be able to autowire HttpServletRequest , though the same doesn't work for HttpServletResponse .

eg.

@Autowired HttpServletRequest request; // works
@Autowired HttpServletResponse response; // doesn't work

There is some discussion about that here -- though in the end it looks like you may have to pass the response manually.

For starters your MailSenderService shouldn't be bothered with creating the TemplateEngine nor know about how to resolve templates, that should be transparant. See this turorial on the Thymeleaf website.

Assuming that you are using XML for bean configuration and Spring 4 add the following. (you probably already have an instance of the ServletContextTemplateResolver configured).

<bean id="webTemplateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
  <property name="prefix" value="/WEB-INF/templates/" />
  <property name="templateMode" value="HTML5" />
  <property name="characterEncoding" value="UTF-8" />
  <property name="order" value="2" />
</bean>

<!-- THYMELEAF: Template Engine (Spring3-specific version) -->
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
  <property name="templateResolvers">
    <set>
      <ref bean="emailTemplateResolver" />
      <ref bean="webTemplateResolver" />
    </set>
  </property>
</bean>

Now in your MailSenderService you can simply inject the TemplateEngine .

@Service
@Qualifier("MailSender")
public class MailSenderService {

@Autowired 
private JavaMailSender mailSender;

@Autowired 
private TemplateEngine engine;

    public boolean sendMail(HttpServletRequest request, HttpServletResponse response, HashMap<String, String> info, String template) throws MessagingException, IOException{

        final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        final MimeMessageHelper message = new 
        MimeMessageHelper(mimeMessage,true, "UTF-8"); // true = multipart

        message.setFrom("sender@example.com");
        message.setTo("mymail@example.com");
        message.setSubject("This is the message subject");

        WebContext ctx =  new WebContext(request, response, 
        request.getServletContext(), request.getLocale());

        ctx.setVariable("info", info);

        try{        
            String messageContent=  engine.process(template, ctx);
            mimeMessage.setContent(tt, "text/html; charset=utf-8");

        }catch(Exception e){
            e.printStackTrace();
        }

        this.mailSender.send(mimeMessage);
        return true;

    }
}

Instead of request.getLocale() simply use LocaleContextHolder.getLocale() and put all the properties you need in your template in your info variable. With this you could rewrite your method to the following.

public boolean sendMail(Map<String, String> info, String template) throws MessagingException, IOException{

        final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        final MimeMessageHelper message = new 
        MimeMessageHelper(mimeMessage,true, "UTF-8"); // true = multipart

        message.setFrom("sender@example.com");
        message.setTo("mymail@example.com");
        message.setSubject("This is the message subject");

        Context ctx =  new Context(LocaleContextHolder.getLocale());
        ctx.setVariable("info", info);

        try{        
            String messageContent=  engine.process(template, ctx);
            mimeMessage.setContent(tt, "text/html; charset=utf-8");

        }catch(Exception e){
            e.printStackTrace();
        }

        this.mailSender.send(mimeMessage);
        return true;

    }

NO need anymore for a HttpServletRequest and HttpServletResponse . Just a plain service. Generally you don't want that your service layer depends on the web as that is what you effectivly did in your solution.

So this is how i solved it with annotations. Big thanks to M. Deinum !

I finally got it all working. I am not using XML. I work with Spring Boot but if I want to configure something, its all in my configuration methods. For everyone lost like I was, here is my configuration of templateEngine in my @Configuration class:

 @Bean
public ClassLoaderTemplateResolver emailTemplateResolver(){
    ClassLoaderTemplateResolver emailTemplateResolver = new      
    ClassLoaderTemplateResolver();
        emailTemplateResolver.setPrefix("/WEB-INF/emails/");
        emailTemplateResolver.setSuffix(".html");
        emailTemplateResolver.setTemplateMode("HTML5");
        emailTemplateResolver.setCharacterEncoding("UTF-8");
        emailTemplateResolver.setOrder(1);
        return emailTemplateResolver;
    }

    @Bean
    public TemplateEngine templateEngine(){
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(emailTemplateResolver());
        return templateEngine;
    }

With this configuration I can just @Autowire

   private TemplateEngine templateEngine; 

In my service and now I do not need request, response. Everything works with Context

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM